7

AsyncTask.cancel(true)内から呼び出した後、AndroidはdoInBackground()呼び出す代わりに、を 呼び出します。しかし、ドキュメントによるとonCancelled()onPostExecute()

このメソッドを呼び出すと、リターンonCancelled(Object)後にUIスレッドで呼び出されdoInBackground(Object[])ます。このメソッドを呼び出すと、が呼び出されないことが保証さonPostExecute(Object)れます。

Androidのバグですか?

その他の所見:

  1. cancel(false)どちらのスレッドからの呼び出しも、ドキュメントで指定されているとおりに機能します。
  2. cancel(true)UIタスクからの呼び出しは、を呼び出しませ。また、以下のlogcatトレースに示されてonPostExecute()いるものをスローしません。InterruptedException
  3. cancel(false/true)スレッドからの呼び出しは、戻る前でも呼び出すことがありonCancelled()ますdoInBackground()これは明らかに、次のように記載されているドキュメントに違反しています。

このメソッドを呼び出すと、 returnsのdoInBackground(Object[])にUIスレッドでonCancelled(Object)が呼び出されます。

コード: (Android2.2デバイスでテスト済み)

protected Void doInBackground(Void... params) {
    Log.d(TAG, "started doInBackground()");
    while (!isCancelled()) {
        boolean ret = cancel(true);
        Log.d(TAG, "cancel() returned: " + ret);
    }
    Log.d(TAG, "returning from doInBackground()");
    return null;
}

Logcat出力

04-15 21:38:55.519: D/MyTask(27597): started doInBackground()
04-15 21:38:55.589: W/AsyncTask(27597): java.lang.InterruptedException
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1254)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:219)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.FutureTask.get(FutureTask.java:82)
04-15 21:38:55.589: W/AsyncTask(27597):     at android.os.AsyncTask$3.done(AsyncTask.java:196)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.FutureTask$Sync.innerCancel(FutureTask.java:293)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.FutureTask.cancel(FutureTask.java:75)
04-15 21:38:55.589: W/AsyncTask(27597):     at android.os.AsyncTask.cancel(AsyncTask.java:325)
04-15 21:38:55.589: W/AsyncTask(27597):     at com.example.test.TestActivity$MyTask.doInBackground(TestActivity.java:31)
04-15 21:38:55.589: W/AsyncTask(27597):     at com.example.test.TestActivity$MyTask.doInBackground(TestActivity.java:1)
04-15 21:38:55.589: W/AsyncTask(27597):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
04-15 21:38:55.589: W/AsyncTask(27597):     at java.lang.Thread.run(Thread.java:1096)
04-15 21:38:55.589: D/MyTask(27597): cancel() returned: true
04-15 21:38:55.589: D/MyTask(27597): returning from doInBackground()
04-15 21:38:55.659: D/MyTask(27597): onPostExecute()
4

2 に答える 2

3
  1. doInBackground()を実行しているスレッドに割り込みを送信するcancel(true)を呼び出すため、例外があります。ただし、この場合、doInBackground()内からcancel(true)を呼び出すため、スレッドはすぐに自分自身に割り込む。

  2. コードはAndroid2で実行されていますが、Android 4のドキュメントを引用しています。問題は、cancel()の動作がAndroid2とAndroid4の間で変更されたことです。

    Android 2.3.7 onPostExecute

    doInBackgroundの後にUIスレッドで実行されます。指定された結果は、doInBackgroundによって返される値であり、タスクがキャンセルされた場合、または例外が発生した場合はnullです。

    Android 4.0.1 onPostExecute

    doInBackgroundの後にUIスレッドで実行されます。指定された結果は、doInBackgroundによって返される値です。タスクがキャンセルされた場合、このメソッドは呼び出されません。

于 2013-04-30T13:50:37.557 に答える
1

nullを返し、onPostExecuteでその戻り値を処理する必要があります。

于 2012-09-18T14:48:25.563 に答える