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ストアで説明されているなぜAsyncTask
WeakReference の回避策を含め、問題が発生する可能性のあるすべてのことをデモしながら使用する必要があります。
このスレッドも参照してください:AsyncTask には本当に概念的な欠陥があるのでしょうか、それとも私が何かを見逃しているだけなのでしょうか?
アップデート:
私はgithubプロジェクトIntentService
別のSOの質問で使用したダウンロードの例(android.os.NetworkOnMainThreadException を修正するには?onActivityResult
) ですが、ここでも関連があると思います。 経由で結果を返すことにより、デバイスを回転させたときに実行中のダウンロードが再起動された に配信されるという追加の利点がありますActivity
。