3

API リファレンスには、次のように記載されています。

AsyncTasks は、理想的には短い操作 (最大で数秒) に使用する必要があります。

スレッドプールがスレッドを使い果たす可能性があるのに、たとえば 30 秒かかる doInBackground に問題がありますか? それが理由である場合、アプリでこのような長時間実行される doInBackground が同時に複数実行されないようにすれば、問題はなくなりますか?

4

2 に答える 2

6

@Walter Mundt の答えは正しいです。それにもかかわらず、補足情報を追加し、長時間実行される AsyncTask に使用できるライブラリへのポインターを提供したいと思います。

AsyncTasks は、バックグラウンドで処理を行うために設計されています。そして、はい、AsyncTask が 2 時間続くと、2 つの異なる問題に直面することになります。

  1. アクティビティはアクティビティのライフ サイクルとの結びつきが弱く、アクティビティが終了すると AsyncTask の結果が得られません。確かに、はい、できますが、それは大雑把な方法です。
  2. AsyncTask は十分に文書化されていません。直感的ではありますが単純な asynctask の実装と使用は、すぐにメモリ リークを引き起こす可能性があります。

@Walter Mundt によって提案された、紹介したいライブラリである RoboSpice は、バックグラウンド サービスを使用してこの種のリクエストを実行します。これはネットワーク リクエスト用に設計されています (本質的に長時間実行される可能性があります) が、ネットワークとは関係のない、長時間実行されるタスクのみを実行するように簡単に適応させることができます。パッチを追加していただけると幸いです。

AsyncTasks が長時間実行されるタスクに適していない理由は次のとおりです。次の推論は、RoboSpice の動機の抜粋からの適応です。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 がデバイス上のリソースを保持するための中心的なメカニズムです。

タスクの進行状況が失われます

いくつかの回避策を使用して、長時間実行される asynctask を作成し、アクティビティのライフ サイクルに従ってそのライフ サイクルを管理できます。アクティビティの onStop メソッドで AsyncTask をキャンセルするか、非同期タスクを終了させ、進行状況を失わずにアクティビティの次のインスタンスに再リンクすることができます。

これは可能であり、RobopSpice の動機でその方法を示していますが、複雑になり、コードは実際には汎用的ではありません。さらに、ユーザーがアクティビティを離れて戻ってきた場合でも、タスクの進行状況は失われます。これと同じ問題がローダーで発生しますが、上記の回避策を再リンクした AsyncTask と同等の単純なものになります。

Android サービスの使用

最適なオプションは、サービスを使用して長時間実行されるバックグラウンド タスクを実行することです。それこそが、RoboSpice が提案するソリューションです。繰り返しますが、これはネットワーキング用に設計されていますが、ネットワークに関係のないものにも拡張できます。このライブラリには多数の機能があります

インフォグラフィックのおかげで、30 秒もかからずにアイデアを得ることができます。


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

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


ネットワークに関連しないタスク (たとえば、キャッシュなし) で RoboSpice の代替手段を探している場合は、Tapeも参照してください。

于 2012-10-30T21:21:59.337 に答える
5

一般に、AyncTasks は、それらを生成したフォアグラウンド アクティビティ スタックにまだ結び付けられているため、たとえば、Activity が AsyncTask を生成した場合、ユーザーがアプリを離れ、OS のメモリが不足すると、Activity のプロセスが強制終了されます (まだ実行中の AsyncTask を含む)、ユーザーがアプリを再開/戻った場合に、状態を復元して最初からやり直すことを期待してください。

実行時間の長いタスク、特に 1 つまたは数個しかない種類のタスクの場合は、代わりに Service が必要になるでしょう。これは、メモリを節約するためにアプリの UI がシャットダウンされても保持できるためです。

免責事項:私はしばらくAndroidのコーディングを行っていないため、この回答は古くなっているか、物事の仕組みの理解に欠陥があることに基づいている可能性があります. より最近の経験を持つ誰かが確認のためにコメントできる場合は、この警告を削除します。高評価の人は、これが正しいことがわかっている場合は、代わりにこの段落を編集してください。

于 2012-08-31T17:35:48.100 に答える