92

hereにあるAsyncTask のドキュメントを引用すると、次のように書かれています。

AsyncTasks は、理想的には短い操作 (せいぜい数秒) に使用する必要があります。スレッドを長時間実行し続ける必要がある場合は、次のような java.util.concurrent パッケージで提供されるさまざまな API を使用することを強くお勧めします。 Executor、ThreadPoolExecutor、および FutureTask。

ここで私の疑問が生じます:なぜですか?関数はdoInBackground()UI スレッドから実行されるため、ここで長時間の操作を実行すると、どのような害があるのでしょうか?

4

4 に答える 4

121

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

  • アクティビティのライフ サイクルとの関連性が低い
  • それらはメモリリークを非常に簡単に作成します。

RoboSpice Motivations アプリ ( Google Play で入手可能)内で、その質問に詳しく答えます。AsyncTasks、ローダー、それらの機能と欠点の詳細なビューを提供し、ネットワーク リクエストの代替ソリューションである RoboSpice も紹介します。ネットワーク リクエストは Android の一般的な要件であり、本質的に長時間実行される操作です。アプリからの抜粋は次のとおりです。

AsyncTask とアクティビティのライフ サイクル

AsyncTask は、Activity インスタンスのライフ サイクルに従いません。アクティビティ内で AsyncTask を開始し、デバイスを回転させると、アクティビティが破棄され、新しいインスタンスが作成されます。しかし、AsyncTask は死ぬことはありません。完成するまで生き続けます。

そして完了すると、AsyncTask は新しいアクティビティの UI を更新しません。実際、表示されなくなったアクティビティの以前のインスタンスを更新します。たとえば、findViewById を使用してアクティビティ内のビューを取得すると、java.lang.IllegalArgumentException: View not attached to window manager というタイプの例外が発生する可能性があります。

メモリリークの問題

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

それにもかかわらず、内部クラスがその外部クラスのインスタンスである Activity.

長期的には、これによりメモリ リークが発生します。AsyncTask が長時間続くと、アクティビティが「生きている」状態に保たれますが、Android はアクティビティを表示できなくなったため、削除したいと考えています。アクティビティはガベージ コレクションできません。これは、Android がデバイス上のリソースを保持するための中心的なメカニズムです。


長時間実行される操作に AsyncTasks を使用することは、非常に悪い考えです。それでも、1 秒または 2 秒後にビューを更新するなどの短命のものには問題ありません。

RoboSpice Motivations アプリをダウンロードすることをお勧めします。これは、これについて詳しく説明し、いくつかのバックグラウンド操作を実行するさまざまな方法のサンプルとデモを提供します。

于 2012-10-26T06:45:55.653 に答える
38

なぜ ?

AsyncTaskはデフォルトで、ユーザーが作成していないスレッド プールを使用するためです。そのプールの要件がわからないため、作成していないプールからリソースを結び付けないでください。また、ここでのケースのように、作成していないプールのリソースを結合しないようにそのプールのドキュメントで指示されている場合は、絶対に結合しないでください。

特に、Android 3.2 以降、AsyncTaskデフォルトで使用されるスレッド プール ( android:targetSdkVersion13 以上に設定されたアプリの場合) には1 つのスレッドしかありません。このスレッドを無期限に拘束すると、他のタスクは実行されません。

于 2012-10-09T11:00:15.473 に答える
4

Aysncタスクは、アプリのGUIで使用することを目的とした特殊なスレッドですが、UIスレッドのリソースを大量に消費するタスクを維持します。したがって、リストの更新、ビューの変更などでフェッチ操作や更新操作を行う必要がある場合は、非同期タスクを使用して、これらの操作をUIスレッドから除外できるようにする必要がありますが、これらの操作は引き続きUIに接続されていることに注意してください。 。

UIの更新を必要としない、実行時間の長いタスクの場合は、UIがなくてもサービスを利用できるため、代わりにサービスを使用できます。

したがって、短いタスクの場合は、スポーンアクティビティが停止した後にOSによって強制終了される可能性があるため、非同期タスクを使用します(通常、操作の途中で停止することはありませんが、タスクは完了します)。また、長く反復的なタスクの場合は、代わりにサービスを使用してください。

詳細については、スレッドを参照してください。

数秒より長いAsyncTask?

アクティビティが破棄されてもAsyncTaskは停止しません

于 2012-10-09T10:11:44.937 に答える