Android の WeakReference/AsyncTask パターン 質問する

Android の WeakReference/AsyncTask パターン 質問する

Android で頻繁に発生するこの単純な状況に関して質問があります。

メイン アクティビティがあり、メイン アクティビティの参照とともに AsyncTask を呼び出すことで、AsyncTask が MainActivity のビューを更新できるようになります。

イベントをステップに分けて説明します

  • MainActivity は AyncTask を作成し、その参照を渡します。
  • AysncTask は作業を開始し、例えば 10 個のファイルをダウンロードします。
  • ユーザーがデバイスの向きを変更しました。これにより、AsyncTask に孤立したポインタが発生します。
  • AsyncTask が完了し、ステータスを更新するためにアクティビティにアクセスしようとすると、null ポインターが原因でクラッシュします。

上記の解決策は、「Pro Android 4」という本で推奨されているように、AsyncTask で WeakReference を保持することです。

WeakReference<Activity> weakActivity;

in method onPostExecute

Activity activity = weakActivity.get();
if (activity != null) {
   // do your stuff with activity here
}

この状況はどうやって解決されるのでしょうか?

私の質問は、asynctask が 10 個のファイルをダウンロードしていて、5 個の完了時にアクティビティが再開された場合 (方向の変更のため)、FileDownloadingTask がもう一度呼び出されるかどうかです。

最初に呼び出された以前の AsyncTask はどうなりますか?

ありがとうございます。質問が長くて申し訳ありません。

ベストアンサー1

この状況はどうやって解決されるのでしょうか?

を使用すると、ガベージコレクションがWeakReference可能になるActivityため、メモリ リークが発生しません。

ヌル参照とは、AsyncTask できないもう接続されていないユーザー インターフェイスを盲目的に更新しようとすると、例外がスローされます (例: ビューがウィンドウ マネージャーに接続されていない)。もちろん、NPE を回避するには null をチェックする必要があります。

私の asynctask が 10 個のファイルをダウンロードしていて、5 個の完了時にアクティビティが再開された場合 (方向の変更のため)、FileDownloadingTask がもう一度呼び出されるでしょうか?

実装によって異なりますが、結果をどこかにキャッシュするなど、意図的に繰り返しダウンロードを不要にする操作を行わない限り、おそらく可能です。

AsyncTask最初に呼び出された以前のものはどうなるでしょうか?

Android の以前のバージョンでは、完了するまで実行され、すべてのファイルをダウンロードした後、それらを破棄します (実装によっては、キャッシュする場合もあります)。

新しいAndroidでは、起動したAsyncTaskと一緒に も終了しているのではないかと疑っていますActivityが、その疑惑の根拠は、ロボスパイス(下記参照) 私の JellyBean デバイスでは実際には漏れません。

アドバイスをさせていただくとすれば、AsyncTaskネットワークなどの長時間実行される可能性のあるタスクを実行するのには適していません。

IntentService単一のワーカー スレッドで十分であれば、これはより優れた (そして比較的単純な) アプローチです。Serviceスレッド プールを制御したい場合は (local) を使用してください。メイン スレッドで作業を行わないように注意してください。

ロボスパイスバックグラウンドで確実にネットワークを実行する方法を探しているなら、これは良いようです(免責事項:私は試していませんし、関係者でもありません)。RoboSpice Motivations デモ アプリPlayストアで説明されているなぜAsyncTaskWeakReference の回避策を含め、問題が発生する可能性のあるすべてのことをデモしながら使用する必要があります。

このスレッドも参照してください:AsyncTask には本当に概念的な欠陥があるのでしょうか、それとも私が何かを見逃しているだけなのでしょうか?

アップデート:

私はgithubプロジェクトIntentService別のSOの質問で使用したダウンロードの例(android.os.NetworkOnMainThreadException を修正するには?onActivityResult) ですが、ここでも関連があると思います。 経由で結果を返すことにより、デバイスを回転させたときに実行中のダウンロードが再起動された に配信されるという追加の利点がありますActivity

おすすめ記事