Activityが破棄されてもAsyncTaskが停止しない
質問
私は
AsyncTask
オブジェクトが実行されると、このオブジェクトは実行を開始します。
Activity
が作成されると実行を開始し、バックグラウンドで何かを行います(最大100枚の画像をダウンロードします)。すべてがうまくいくのですが、理解できない奇妙な動作があります。
例えば
アンドロイドの画面の向きが変わると
Activity
は破棄され、再度作成されます。そこで、私は
onRetainNonConfigurationInstance()
メソッドをオーバーライドし、実行されたすべてのダウンロードされたデータの保存を
AsyncTask
. このようにする目的は
AsyncTask
が実行されるたびに
Activity
が破壊され作成されるのですが、ログで見る限り、前の
AsyncTask
は実行されたままです。(データは正しく保存されていますが)
をキャンセルしようとしても
AsyncTask
の中にある
onDestroy()
メソッドを作成しましたが、ログにはまだ
AsyncTask
が実行されていると表示されます。
これは本当に不思議な動作です。
AsyncTask
.
どのように解決するのですか?
ロマンガイの回答は正しいです。しかし、私は情報を補足し、長時間実行する AsyncTask、さらにネットワーク指向の Asynctask に使用できるライブラリまたは 2 つへのポインタを提供したいと思います。
AsyncTasksはバックグラウンドで何かを行うために設計されています。そして、そうです、あなたは
cancel
メソッドを使って停止できます。インターネットから何かをダウンロードする場合、私は強くお勧めします。
が IO ブロッキング状態になっているときは、 スレッドに気を配ることです。
. あなたは、次のようにダウンロードを整理する必要があります。
public void download() {
//get the InputStream from HttpUrlConnection or any other
//network related stuff
while( inputStream.read(buffer) != -1 && !Thread.interrupted() ) {
//copy data to your destination, a file for instance
}
//close the stream and other resources
}
を使うことで
Thread.interrupted
フラグを使用すると、スレッドがブロッキングされた io 状態を適切に終了できるようになります。を呼び出すと、スレッドがより反応するようになります。
cancel
メソッドの呼び出しに反応しやすくなります。
AsyncTaskの設計上の欠陥
しかし、AsyncTaskがあまりにも長く続くと、2つの異なる問題に直面することになります。
- アクティビティがライフサイクルとうまく連携しておらず、アクティビティが終了するとAsyncTaskの結果を得られない。確かに、そうですが、それは荒っぽい方法でしょう。
- AsyncTaskはあまりよく文書化されていない。直感的ではあるが、素朴な実装と非同期タスクの使用は、すぐにメモリリークにつながる可能性がある。
RoboSpice 今回紹介するライブラリ RoboSpice は、このようなリクエストを実行するためにバックグラウンドサービスを使用しています。これはネットワークからのリクエストを想定して設計されている。また、リクエストの結果を自動的にキャッシュするなどの機能も備えている。
ここで、AsyncTasksが長時間実行されるタスクに向かない理由を説明します。以下の理由は、以下の記事から抜粋したものです。 RoboSpiceの動機 : 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 がデバイス上のリソースを維持するための中心的なメカニズムです。
タスクの進行状況は失われます
長時間稼働する非同期タスクを作成し、そのライフサイクルをアクティビティのライフサイクルに従って管理するために、いくつかの回避策を使うことができます。次のいずれかを行います。 アクティビティのonStopメソッドでAsyncTaskをキャンセルする。 または、非同期タスクを終了させ、その進捗を失わないようにして アクティビティの次のインスタンスに再リンクさせます。 .
これは可能で、RobopSpiceのmotivationsでその方法を紹介していますが、複雑になってしまい、コードも汎用的ではありません。さらに、ユーザがアクティビティから離れ、戻ってきた場合、タスクの進行状況は失われたままです。これと同じ問題はローダーにも現れますが、上記の再リンクによるAsyncTaskの回避策と同等により単純なものになります。
Android サービスを使用する
最良の選択肢は、長時間実行されるバックグラウンド タスクを実行するためにサービスを使用することです。これはまさに RoboSpice が提案するソリューションです。繰り返しますが、これはネットワーク用に設計されていますが、ネットワークに関連しないものにも拡張できます。このライブラリには 多数の機能 .
のおかげで、30秒足らずでそのイメージをつかむこともできます。 インフォグラフィックス .
AsyncTasksを長時間実行する操作に使用するのは、本当に非常に悪い考えです。しかし、1~2秒後にビューを更新するような短時間実行のものには問題ありません。
私はあなたが RoboSpice Motivationsアプリ このアプリは、ネットワークに関連するさまざまな方法のサンプルやデモを提供し、この問題を深く説明しています。
ネットワークに関連しないタスク(たとえばキャッシュなし)で RoboSpice の代替品をお探しなら、次のサイトも参照してください。 テープ .
関連
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] インスタンス状態の保存を使用してアクティビティ状態を保存するにはどうすればよいですか?
-
[解決済み] アクティビティで本来追加されるウィンドウが流出した
-
[解決済み] ViewPagerとフラグメント - フラグメントの状態を保存する正しい方法は何ですか?
-
[解決済み] FragmentのsetRetainInstance(boolean)を理解する。
-
[解決済み】バックグラウンドタスク、プログレスダイアログ、オリエンテーションの変更 - 100%動作する解決策はありますか?
-
[解決済み] プログラムでソフトキーボードを開く
-
[解決済み] Gmailの3分割アニメーションシナリオの完全動作サンプル?
-
[解決済み] Androidのadb logcatでTAG名で特定のメッセージを除外する方法は?
-
[解決済み] サポートライブラリのアクションバーをPreferenceActivityに追加するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】AsyncTaskは本当に概念的に欠陥があるのか、それとも私が何かを見逃しているだけなのか?
-
[解決済み] Nexus 4でUSBデバッグモードを見つける方法とオンにする方法
-
[解決済み] プログラム的に電話をかけるには?
-
[解決済み] handler.postDelayed()を停止する。
-
[解決済み] Android Navigation Architecture Component - 現在表示されているフラグメントを取得する
-
[解決済み] EditTextの右側のDrawableにonClickListenerを設定する [重複] [重複
-
[解決済み] Android Lintが翻訳されていない文字列を訴えないようにする。
-
[解決済み] Androidでツールバーの戻るボタンの色を変えるには?
-
[解決済み] FABアイコンの色を設定する
-
[解決済み] Android AsyncTaskによる長時間動作の実現