1. ホーム
  2. android

[解決済み] Android AsyncTaskによる長時間動作の実現

2023-03-02 02:33:03

質問

AsyncTaskのドキュメントを引用すると、以下のようになります。 ここで と書いてあります。

AsyncTasksは理想的には短い操作(せいぜい数秒)のために使われるべきです。もしスレッドを長時間動かし続ける必要があるなら、Executor、ThreadPoolExecutor、FutureTaskといったjava.util.concurrentパッケージが提供する様々なAPIを使うことを強く推奨します。

ここで私の疑問が生じます。それは doInBackground() 関数はUIスレッドから実行されるので、ここで長時間実行することで何か不都合があるのでしょうか?

どのように解決するのですか?

非常に良い質問ですね。Android プログラマとして、この問題を完全に理解するには時間がかかります。実際、AsyncTask には、関連する 2 つの主要な問題があります。

  • アクティビティのライフ サイクルにうまく関連付けられていない
  • メモリリークが発生しやすい

の内部には ロボスパイス モチベーションアプリ( Google Playで公開中 ) では、その質問に詳しくお答えします。AsyncTasks、Loader、それらの特徴や欠点について詳しく説明し、さらにネットワークリクエストの代替ソリューションである : RoboSpice ネットワークリクエストは Android では一般的な要件であり、その性質上、長時間実行される操作である。 . 以下はアプリからの抜粋です。

AsyncTask と Activity のライフサイクル

AsyncTaskはActivityインスタンスのライフサイクルに従わない。Activity内でAsyncTaskを起動し、デバイスを回転させると、Activityは破棄され、新しいインスタンスが作成されます。しかし、AsyncTaskは死なない。完了するまで生き続けるのです。

そして完了したとき、AsyncTaskは新しいActivityのUIを更新しません。実際、もう表示されていないアクティビティの以前のインスタンスが更新されます。 が表示されなくなります。これは、java.lang.IllegalArgumentException.View not attached to window manager というタイプの例外につながる可能性があります。ビューがウィンドウマネージャにアタッチされていない場合 を使用している場合、例えば、findViewByIdでアクティビティ内のビューを取得します。

メモリリークの問題

アクティビティの内部クラスとしてAsyncTasksを作成するのは非常に便利です。AsyncTask はタスクが完了または進行しているときに Activity のビューを操作する必要があるため、Activity の内部クラスを使用することは非常に便利です。 タスクが完了または進行中のとき、Activityの内部クラスを使用することは便利です:内部クラスは、外部クラスの任意のフィールドに直接アクセスできます。 内部クラスは外部クラスの任意のフィールドに直接アクセスすることができます。

とはいえ、これは内部クラスが外部クラスのインスタンスであるActivityの見えない参照を保持することを意味します。

AsyncTaskが長く続くと、アクティビティが生かされます。 一方、Android は、もはや表示できないので、それを取り除きたいと考えています。アクティビティはガベージコレクトされないので、これはAndroidがリソースを保存するための中心的なメカニズムです。 Android がデバイス上のリソースを維持するための中心的なメカニズムです。


AsyncTasksを長時間実行する操作に使用するのは、本当に非常に悪い考えです。しかし、1~2秒後にビューを更新するような短時間実行のものには問題ありません。

私はあなたが RoboSpice Motivationsアプリ このアプリは、このことを深く説明し、いくつかのバックグラウンド操作を行うためのさまざまな方法のサンプルとデモを提供しています。