GingerbreadとICSでのAsyncTaskの挙動の違い

元ネタはこちら。正確にはAPI level 1113以上から違うらしい。

API LEVEL 11以上のAsyncTaskの振る舞いについて - Google グループ

お試しソース。名前とか超適当なのはご勘弁を。

package net.swingingblue.andorid.asynctaskics;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class AsyncTaskIcsActivity extends Activity {

	private static final String LOG_TAG = "AsyncTaskIcsSample";
	
	private AsyncTask<Void, Void, Void> task1 = new SampleAsyncTask();
	private AsyncTask<Void, Void, Void> task2 = new SampleAsyncTask2();
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		
		Button button = (Button)findViewById(R.id.button1);
		button.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				task1.execute();
				task2.execute();
			}
		});
	}
	
	private class SampleAsyncTask extends AsyncTask<Void, Void, Void> {

		@Override
		protected Void doInBackground(Void... params) {
			Log.d(LOG_TAG, "SampleAsyncTask#doInbackground entered.");

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			Log.d(LOG_TAG, "SampleAsyncTask#doInbackground go out.");
			return null;
		}

	}

	private class SampleAsyncTask2 extends AsyncTask<Void, Void, Void> {

		@Override
		protected Void doInBackground(Void... params) {
			Log.d(LOG_TAG, "SampleAsyncTask2#doInbackground entered.");

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			Log.d(LOG_TAG, "SampleAsyncTask2#doInbackground go out.");
			
			return null;
		}
	}
}

結果。タイムスタンプとスレッド番号に着目。

Gingerbread(API level 10)

01-24 17:39:21.384   340   349 D AsyncTaskIcsSample: SampleAsyncTask#doInbackground entered.
01-24 17:39:21.424   340   350 D AsyncTaskIcsSample: SampleAsyncTask2#doInbackground entered.
01-24 17:39:22.398   340   349 D AsyncTaskIcsSample: SampleAsyncTask#doInbackground go out.
01-24 17:39:22.474   340   350 D AsyncTaskIcsSample: SampleAsyncTask2#doInbackground go out.

ICS(API level 15)

01-24 17:34:51.124   730   743 D AsyncTaskIcsSample: SampleAsyncTask#doInbackground entered.
01-24 17:34:52.179   730   743 D AsyncTaskIcsSample: SampleAsyncTask#doInbackground go out.
01-24 17:34:52.185   730   744 D AsyncTaskIcsSample: SampleAsyncTask2#doInbackground entered.
01-24 17:34:53.190   730   744 D AsyncTaskIcsSample: SampleAsyncTask2#doInbackground go out.

ふむふむ。

ICSではdoInBackground()の中でwaitとかやってたりすると、他のAsyncTaskをexecute()しても動かない、と。まぁ複数スレッドの待ち合わせにAsyncTaskは使わずにExecutors.newCachedThreadPool()とかしろってことですね。

(追記)

task1.execute();

の代わりに

task1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

とすればlevel 12以前の動作と同じになるみたい。
(追記おわり)

まぁGingerbread上で作ったソースをそのまま持って来てあっさり動くと思ってるとダメなケースがあると。使い方の問題でもあるのだけど。

タイトルとURLをコピーしました