読者です 読者をやめる 読者になる 読者になる

プログラマってこんなかんじ??

アプリ作ったり歌ったりしてます

AsyncTask の挙動が異なる(AsyncTask#executeOnExecutor)

Android

AsyncTask の挙動が Gingerbread と ICS で違う、という話を聞いて調べてみた。

複数AsyncTask実行=バックグラウンドで並行処理 と考えてると、実は並行処理になってなくて処理が遅い、ってこと。

結論を言うと、ソースをここだけ修正すればよさそう。

修正方法

  • AsyncTask#execute を AsyncTask#executeOnExecutor に変更する
  • AsyncTask#executeOnExecutor の引数に AsyncTask.THREAD_POOL_EXECUTOR を指定する


1行で済みそうな修正。よかったw
とはいえ気になったので、AsyncTask#execute の挙動の違いについてまとめてみる。
↓はSDKのバージョンを変えて検証した結果。

検証結果

複数AsyncTask の AsyncTask#execute を実行した場合

  • API Level 1012まで
    • 複数バックグラウンド処理がパラレルで実行される
  • API Level 1113以降
    • 複数バックグラウンド処理がシリアルで実行される


3.2 から変わった様子。
ちなみに検証はこんなかんじで。

検証方法

  • ビルドには ICS(API Level14) を使用
  • 以下のパターンのapkを作成
    • AndroidManifest.xmlandroid:minSdkVersion を11〜14の間で変更したapkを作成
  • emulator(API Level14) 上で実行


では、GB相当の AsyncTask と同等の動きをさせるにはどうしたらいいか。
AsyncTask#executeJavadoc見るとこう書いてある。

After HONEYCOMB, it is planned to change this back to a single thread 
to avoid common application errors caused by parallel execution. 
If you truly want parallel execution, 
you can use the executeOnExecutor(Executor, Params...) 
version of this method with THREAD_POOL_EXECUTOR; 
however, see commentary there for warnings on its use.

Honeycomb以降では 複数のAsyncTackのバックグラウンド処理 をパラで実行したいなら
AsyncTask#executeOnExecutor + THREAD_POOL_EXECUTOR を使用してください、と。


今回使用したサンプル。
(ボタン押したら AsyncTask#execute か AsyncTask#executeOnExecutor を実行するだけ)

実行結果(emulator(API Level14))

AsyncTask#execute
01-25 02:58:37.899: D/AsyncTaskTest(613): [doInBackground]start 78
01-25 02:58:39.950: D/AsyncTaskTest(613): [doInBackground]end   78
01-25 02:58:39.950: D/AsyncTaskTest(613): [doInBackground]start 79
01-25 02:58:41.970: D/AsyncTaskTest(613): [doInBackground]end   79
AsyncTask#executeOnExecutor
01-25 02:59:11.889: D/AsyncTaskTest(613): [doInBackground]start 80
01-25 02:59:11.929: D/AsyncTaskTest(613): [doInBackground]start 81
01-25 02:59:13.919: D/AsyncTaskTest(613): [doInBackground]end   80
01-25 02:59:13.989: D/AsyncTaskTest(613): [doInBackground]end   81

AsyncTask#executeOnExecutor の方はちゃんとパラで動いてる。

参考

@findup さんのエントリ。
[http://www.swingingblue.net/mt/archives/003629.html:title=きままな日記帳 - GingerbreadとICSでのAsyncTaskの挙動の違い