AsyncTask止まらない場合でも、活動を破壊
-
22-09-2019 - |
質問
いAsyncTaskオブジェクトを開始する実行時の動作とは、背景ダウンロード100画像)を実現します。全ての色がこの特異な挙動をするっていきます。
用例:のandroid画面の向きを変更しての活動が破壊され、作成されます。私はオーバーライドのonRetainNonConfigurationInstance()メソッドを保存すべてのダウンロードしたデータで実行されAsyncTask.私の目的で行うことになっていAsyncTask実行時には破壊され作成されたオリエンテーション時に変化していましたが、もともとついての私のログは、前AsyncTaskだ。(データが保存され正しいもの)
もう消すのAsyncTaskのonDestroy()メソッドの活動が、ログを示しているもののAsyncTaskしています。
これは本当に不思議な行動をとうかされていることに感謝しばしくは今後公式サイトにて正しい手順を停止解除のAsyncTask.
感謝
解決
その答えを与えるには以下のようにCgiのような正しい。しかし、付け加えたいと思い補完の情報を指すポインター図書室または2に使用できる長期のAsyncTaskともネットワーク指向のasynctasks.
AsyncTasksて設計されているというものです。トがありますの cancel
方法。としてダウンロードしたものの、インターネットからのいっ ケーススレッドがこのオブロック状態.きをコンテンツのダウンロードしました。
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でないものが記録されている。るナイーブが直感的に、実施およびご使用になasynctaskでメモリ解放されます。
RoboSpice, の図書館についてご紹介を使用して背景のサービスを実行このようなのです。そのためにネットワークです。この追加などの特徴を自動キャッシュの要望'ます。
ここでは、そのAsyncTasksが悪いのではなく長く走ります。以下のreasonningは適応からexerptsの RoboSpice動機 :このアプリを説明する理由RoboSpiceは充填する必要のAndroidプラットフォーム.
のAsyncTask活動の生活サイクル
AsyncTasksなォ活動のインスタンスの生活サイクルです。開始された場合は、AsyncTask内の動きを回転させるデバイスの活動を破壊する、新しいインスタンスを作成します。そのAsyncTaskません。で生までが完了します。
及び完成時には、AsyncTaskな更新UIの新しい活動です。確かにそれを更新する前のインスタンスの活動 を表示しないようにしました。このことは例外の型をjava.lang.IllegalArgumentException:ビューに付いていないウィンドウマネージャの場合 ご利用いただくためには、スfindViewById検索ビュー内の活動です。
メモリリークの問題
とても便利でをAsyncTasksとしての内部クラスです。としてのAsyncTask必要なものを操作するの意見 活動の場合、タスク完了または進行中の内部クラスの活動のように便利な:内部クラスで アクセスを直接分野の外側のクラスです。
しかし、この内部クラスを開催し目に見えない参考となるその外側のクラスのインスタンス:ての活動となりました。
ので、長期的にはこのメモリリーク:場合にはAsyncTask続長での活動を"生きて" はAndroidいをなくすことはできないと表示されます。この活動できないゴミ収集したことになる中央 機構Androidの保全資源の装置です。
進のデータベースは失われます
利用できる一部の回避策を長期asynctask管理ライフサイクルに従ってのライフサイクルにわたって活動です。きのいずれか 解除のAsyncTaskのonStop法の活動 きをした非同期タスクの仕上がり、ゆったり、その進捗や relinkでのインスタンスの活動.
することを可能としてどのようにRobopSpice渋沢スカラープログラム"に参加がで複雑なコードによってクラスを提供します。.また、今もゆったりの進捗をタスクの場合、ユーザーの活動。この問題を画面が表示されるローダがこのプと同等のAsyncTaskとrelinking回避策mentionnedます。
使用Androidサービス
最良のオプションを利用サービスの実行を行う長期の背景事ができます。その溶液を提案するRoboSpice.再度、設計になっていますネットワークができる非ネットワーク関連のもの。このライブラリは、 多数の特徴.
することができますので以下30秒の インフォグラフィックス.
とっても非常に悪い"というアイデアAsyncTasks長走ります。しかしながら、これはや豪雨で、地滑りや洪水などの短い生きもの更新などの見後1-2秒です。
り組んでいただきたいと思いますがダウンロード RoboSpice動機のアプリ, でも説明しているこの深い、サンプルのデモの異なる方法をいくつかのネットワーク関連のもの。
場合に代わるものを探しているRoboSpice外ネットワーク関連業務(インスタンスなキャッシュ)として テープ.
他のヒント
一般に、以下のようなものと同様のものを使用してリストインスタンスとデータをプロビジョニングすることができます。
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<ListInstance Title="My Survey"
OnQuickLaunch="TRUE"
TemplateType="102"
FeatureId="00bfea71-2062-426c-90bf-714c59600103"
Url="Lists/Survey"
Description="">
<Data>
<Rows>
<Row>
<Field Name='Title'>My title field value</Field>
</Row>
</Rows>
</Data>
</ListInstance>
</Elements>
.
しかし、調査がより「特別」であるので、実際の質問があなたのリストへの列の列 - そして最も文書化されていない(フィールドタイプの面で( http://msdn.microsoft.com/en-us/library/ms948164.aspx )
だからあなたは実際に列の質問を定義する必要があるでしょうが、実際の応答は "data"要素にあります。質問が特定の名前を持つカスタムフィールドとして定義されるので、質問フィールドを含める必要があります。このフィールドはフィールド定義スキーマと一致する必要があります。一つの代替案は、リストをSTPとしてエクスポートし、マニフェストの内側を見ていることがあります。
次のように試してみてください(例:Likert Scaleの同等のものを見つけることができませんでした - しかし単純な質問は通常の列としてあるべきです)。区切り文字列の場合も、「PagePeparator」のフィールドが基本的に調査でページブレークを挿入することを発見しました。
<Field Type="Choice" DisplayName="Question 1" Required="FALSE" Format="RadioButtons" FillInChoice="FALSE" ID="YOUR_GUID_MUST_GO_HERE" StaticName="Question_x0020_1" Name="Question_x0020_1" ColName="nvarchar3" RowOrdinal="0"><CHOICES><CHOICE>Enter Choice #1</CHOICE><CHOICE>Enter Choice #2</CHOICE><CHOICE>Enter Choice #3</CHOICE></CHOICES></Field>
. 以下は問題を解決しませんが、それを防ぎます。アプリでマニフェストを行います。
<activity
android:name=".(your activity name)"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden|screenSize" > //this line here
</activity>
これを追加すると、アクティビティは構成の変更にリロードされません。また、オリエンテーションが変更されたときに変更を行いたい場合は、アクティビティの次の方法をオーバーライドします。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//your code here
}
アクティビティはオリエンテーションの変更で再現されます、はい、それは本当です。ただし、このイベントが発生するたびにAsynctaskを継続できます。
あなたはそれをチェックします
@Override
protected void onCreate(Bundle savedInstanceState) {
if ( savedInstanceState == null ) {
startAsyncTask()
} else {
// ** Do Nothing async task will just continue.
}
}
-乾杯
から MVC 視点、アクティビティはです コントローラ;それは間違っています コントローラ より長生きする操作を実行する 意見 (Android.view.viewから派生した、通常は既存のクラスを再利用するだけです)。したがって、それはであるべきです モデル非同期を開始する責任。
Asynctaskがスレッドプール(並列処理)にない場合、CPUによって既に実行されており、CPUが無料で実行された後、停止またはキャンセルコマンドが実行されるため、Asynctaskの実行を停止できません(CPUはAsynctaskで行われます)。ただし、スレッドプールでは、タスクがキューに登録され、1つずつ実行されます。したがって、キャンセルコマンドがAsyncタスクの実行中にキューに掲載された場合、非同期タスクを停止できます。
使用できます class MagicAppRestart
から この郵便受けに プロセスを殺します すべての非同期とともに。 Androidはアクティビティスタックを復元します(ユーザーは何も言及しません)。プロセスの再起動前の唯一の通知は呼び出していることに注意することが重要です onPause()
;による Androidアプリライフサイクルロジック, 、とにかくあなたのアプリケーションはそのような終了の準備ができている必要があります。
私はそれを試しました、そしてそれはうまくいくようです。それにもかかわらず、私はアプリケーションクラスからの弱い参照のような「より文明化された」方法を使用する予定の瞬間(私の非同期はかなり短命であり、できればそれほど多くのメモリを消費しない)。
これがあなたがプレイできるいくつかのコードです:
MagicApprestart.java
package com.xyz;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
// Do not forget to add it to AndroidManifest.xml
// <activity android:name="your.package.name.MagicAppRestart"/>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.exit(0);
}
public static void doRestart(Activity anyActivity) {
anyActivity.startActivity(new Intent(anyActivity.getApplicationContext(), MagicAppRestart.class));
}
}
残りは、Eclipseが新しいAndroidプロジェクトのために作成したものです com.xyz.asynctasktastactivity:
asynctaskTestactivity.java
package com.xyz;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class AsyncTaskTestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d("~~~~","~~~onCreate ~~~ "+this);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onStartButton(View view) {
Log.d("~~~~","~~~onStartButton {");
class MyTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
Log.d("~~~~","~~~doInBackground started");
try {
for (int i=0; i<10; i++) {
Log.d("~~~~","~~~sleep#"+i);
Thread.sleep(200);
}
Log.d("~~~~","~~~sleeping over");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("~~~~","~~~doInBackground ended");
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
taskDone();
}
}
MyTask task = new MyTask();
task.execute(null);
Log.d("~~~~","~~~onStartButton }");
}
private void taskDone() {
Log.d("~~~~","\n\n~~~taskDone ~~~ "+this+"\n\n");
}
public void onStopButton(View view) {
Log.d("~~~~","~~~onStopButton {");
MagicAppRestart.doRestart(this);
Log.d("~~~~","~~~onStopButton }");
}
public void onPause() { Log.d("~~~~","~~~onPause ~~~ "+this); super.onPause(); }
public void onStop() { Log.d("~~~~","~~~onStop ~~~ "+this); super.onPause(); }
public void onDestroy() { Log.d("~~~~","~~~onDestroy ~~~ "+this); super.onDestroy(); }
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:text="Start" android:onClick="onStartButton" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<Button android:text="Stop" android:onClick="onStopButton" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xyz"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".AsyncTaskTestActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MagicAppRestart"/>
</application>
</manifest>
そしてログの関連部分(それに注意してください それだけ onPause
呼ばれています):
D/~~~~ (13667): ~~~onStartButton {
D/~~~~ (13667): ~~~onStartButton }
D/~~~~ (13667): ~~~doInBackground started
D/~~~~ (13667): ~~~sleep#0
D/~~~~ (13667): ~~~sleep#1
D/~~~~ (13667): ~~~sleep#2
D/~~~~ (13667): ~~~sleep#3
D/~~~~ (13667): ~~~sleep#4
D/~~~~ (13667): ~~~sleep#5
D/~~~~ (13667): ~~~sleep#6
D/~~~~ (13667): ~~~sleep#7
D/~~~~ (13667): ~~~sleep#8
D/~~~~ (13667): ~~~sleep#9
D/~~~~ (13667): ~~~sleeping over
D/~~~~ (13667): ~~~doInBackground ended
D/~~~~ (13667):
D/~~~~ (13667):
D/~~~~ (13667): ~~~taskDone ~~~ com.xyz.AsyncTaskTestActivity@40516988
D/~~~~ (13667):
D/~~~~ (13667): ~~~onStartButton {
D/~~~~ (13667): ~~~onStartButton }
D/~~~~ (13667): ~~~doInBackground started
D/~~~~ (13667): ~~~sleep#0
D/~~~~ (13667): ~~~sleep#1
D/~~~~ (13667): ~~~sleep#2
D/~~~~ (13667): ~~~sleep#3
D/~~~~ (13667): ~~~sleep#4
D/~~~~ (13667): ~~~sleep#5
D/~~~~ (13667): ~~~onStopButton {
I/ActivityManager( 81): Starting: Intent { cmp=com.xyz/.MagicAppRestart } from pid 13667
D/~~~~ (13667): ~~~onStopButton }
D/~~~~ (13667): ~~~onPause ~~~ com.xyz.AsyncTaskTestActivity@40516988
I/ActivityManager( 81): Process com.xyz (pid 13667) has died.
I/WindowManager( 81): WIN DEATH: Window{4073ceb8 com.xyz/com.xyz.AsyncTaskTestActivity paused=false}
I/ActivityManager( 81): Start proc com.xyz for activity com.xyz/.AsyncTaskTestActivity: pid=13698 uid=10101 gids={}
I/ActivityManager( 81): Displayed com.xyz/.AsyncTaskTestActivity: +44ms (total +65ms)
D/~~~~ (13698): ~~~onCreate ~~~ com.xyz.AsyncTaskTestActivity@40517238