Android 開発でユーザービリティを向上させるのに良く利用する AsyncTask ですが、cancel した時の内部の動作が不明だったので調べまてみました。 知りたいのは、 「cancel を呼び出したら、doInBackgroud で行われている処理はどうなるのか?」 です。
そこで用意したのが下のプログラムです。 これはクラス変数 count を MyTask によって 100 まで加算します。 MyTask のインスタンスを二つ用意し、
という処理をしています。 タスク A と B で count は共有しています。
AsyncTask のテストプログラム1
public class AsyncTestActivity extends Activity {
private int count = 0;
private MyTask task = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button)findViewById(R.id.Button01);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
// タスク A を実行
task = new MyTask("taskA");
task.execute((Void)null);
// 5秒待つ
SystemClock.sleep(5000);
// タスク A を中断
task.cancel(true);
// タスク B を実行
task = new MyTask("taskB");
task.execute((Void)null);
}
});
}
/** 非同期で加算を行う内部クラス */
class MyTask extends AsyncTask {
private String name = "";
MyTask(String name) {
this.name = name;
}
/** 非同期処理 */
@Override
protected Long doInBackground(Void... params) {
long start = System.currentTimeMillis();
// count を 0~100 まで 100ms 毎に加算する処理
count = 0;
for (int i = 0; i < 100; i++) {
SystemClock.sleep(100);
count++;
}
// 処理にかかった時間を返す
return System.currentTimeMillis() - start;
}
/** doInBackground が終わったら呼び出される。 */
@Override
protected void onPostExecute(Long result) {
// 結果を表示 "タスク名 - カウンタ値 - 処理時間ms"
Toast.makeText(AsyncTestActivity.this,
name + " - " + String.valueOf(count) + " - "
+ String.valueOf(result) + "ms",
Toast.LENGTH_LONG).show();
}
}
}
まず前提として、タスクを1つだけ実行した時は、こんな結果になります。
###タスク A だけを実行した時の結果
>taskA - 100 - 100029ms
100ミリ秒毎に100回加算しているので、妥当な結果といえます。
このコードを実行すると次のような結果になりました。
#### テストプログラム1の結果
>taskB - 151 - 100031ms
taskA の結果は出力されないので cancel した場合は onPostExecute は呼び出されない事が分かります。
しかし、カウント値が 151 と異常になってます。 どうやら taskA と taskB が並列処理されてしまっているようです。 なので、cancel を呼び出しても、doInBackground の処理は継続して行われている事が分かります。
今回分かったことは
* AsyncTask.cancel を呼ぶと、onPostExecute は呼び出されない。
* AsyncTask.cancel を呼んだだけでは doInBackground の処理は中断されない。
です。
じゃあ、どうやって中断させようか、という事で次回↓へ続く。
AsyncTask を cancel した時の動き【その2】