AsyncTask の挙動が異なる(AsyncTask#executeOnExecutor)
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 から変わった様子。
ちなみに検証はこんなかんじで。
検証方法
では、GB相当の AsyncTask と同等の動きをさせるにはどうしたらいいか。
AsyncTask#execute のJavadoc見るとこう書いてある。
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の挙動の違い