Android で長い (時間のかかる) アクションを整理するにはどうすればよいですか?
-
19-09-2019 - |
質問
たとえば、SomeActivity にいて、そのアクティビティには、あるディレクトリから別のディレクトリへのファイルの移動 (ジョブと呼びます) を呼び出すボタンがあります。
BlackBerry では次のようにします。
- 「お待ちください…」というキャンセル不可のポップアップ(ダイアログ画面)を押す
- ジョブを実行するスレッドを開始する
- スレッドの完了時にポップアップを閉じる
このアプローチでは、タスク終了後も同じ画面に留まることが 99.99% 保証され、ユーザーはポップアップを確認してジョブの完了を待つだけです。デバイスの回転などによって、目的のワークフローが中断されることはありません。
Android では状況が変わります。おそらく私のケースを解決するために提供されている AsyncTask があることはわかっています。良いものもあります 例 どのように使用すべきかについて。ただし、Activity インスタンスがどれくらい存続するかについては保証がないため、AsyncTask は onSaveInstanceState でキャンセルされる必要があります (そして onRestoreInstanceState で再起動される)。これは、AsyncTask を使用すると、開始されたジョブを完全に実行できるという保証がないことを意味します。場合によっては、ユーザーを作成するために http post リクエストを送信するときに、AsyncTask を再実行するときに「このログインにはユーザーがすでに存在します」という問題が発生したくないことがあります。これが可能なのは、リクエストがすでに送信されている間 (サーバーが実際に新しいユーザーの作成というジョブを実行している間)、AsyncTask を中断できるためですが、応答を取得する前に AsyncTask がキャンセルされるからです。
Android で上記の BB のような動作を実現する解決策はありますか?
解決 3
2010年5月にGoogleは<のhref = "http://www.google.com/intl/uk-UA/events/io/2010/sessions/developing-RESTful-android-appsと呼ばれる新しいIOセッションを発行しました。 htmlの」relが= 『nofollowを』>私が尋ねた正確に何を達成する方法を説明するのAndroid RESTクライアントアプリケーションの開発ます。
これは質問がかなり複雑なので、簡単なかつ迅速な解決策はありませんが判明しました。ソリューションは、Androidプラットフォーム/ APIの深い知識が必要です。これは、アプリのプロセス/アクティビティのライフサイクルの柔軟性によって引き起こされる価格です。
私は、この情報はアンドロイドの非常に最初のバージョンから提示されなかった理由について、いくつかの奇妙に感じます。 Googleが100%buglessアプリケーションを書くとアプローチを共有していなかったいくつかのマーケティング上の理由のためにする方法を知っていたように見えます。ただ、2010年5月によって書かれたどのように多くのバグがアプリを想像します。
とにかく、私はうれしい今、私たちはベストプラクティスのアプローチをなめらか呼び出しています。
他のヒント
しかし、どのようにの保証はありませんので、 長い活動インスタンスが住むことになります AsyncTaskは上キャンセルする必要があります onSaveInstanceState(との再起動 onRestoreInstanceState)。
それとも、Service
によって管理されています。
あなたのアクティビティが画面上に滞在したい場合、あなたは、単にこのようなスレッドを起動することができます:
final File fromFile = ...;
final File toFile = ...;
new Thread() {
@Override
public void run() {
// do something with fromFile, toFile
}
}.start();
GUIスレッドは、他の操作を行う準備ができていることの方法は、
を表示するように考えています android.app.ProgressDialog
また、
との対話がuncancellableすることを検討 ProgressDialog.setCancelable(false);
ユーザーがあなただけはときの通知を受けるHOMEキー、経由残すことができますこの方法
Activity.onPause()
が呼び出されます。 Futhermoreあなたは黒とそれが殺されるかもしれない背景にプッシュされ、アプリケーションを回してから画面を停止するには、Wakelocksに見たいと思うかもしれません。あなたがスレッドでこれを行うと思います:
PowerManager pm = (PowerManager) ivContext.getSystemService(Context.POWER_SERVICE);
Wakelock wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "MyApp");
wakeLock.acquire();
// ... copy stuff ...
wakeLock.release();
もちろん、ユーザーがHOMEキーを経由して離れたとき、あまりにも、wakeLockを解放する必要があると思います。
あなたは、バックグラウンドスレッドからGUI要素を呼び出したい場合は、通常のスレッドは、あなたが上で呼び出さなったときに、で実行されているように、スレッドは、GUI-イベントループの一部である場合は、最後に、これはのみ動作します...-方法。これを達成するために、あなたのバックグラウンドスレッドは、ハンドラを経由してGUIスレッドにコールバックする必要があります。このように:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.v(TAG, "Got Message "+msg.what); // prints: Got Message 77
// ... do GUI actions ...
}
};
// ... in Thread ...
int lvInfo = 77;
mHandler.sendEmptyMessage(lvInfo);
あなたもそうのようなメッセージ内のオブジェクトを置くことができます:
Message txtMsg = Message.obtain();
textMsg.obj = "Hello World";
mHandler.sendMessage(lvTextMsg);