7

AsyncTask.cancel(true)从内部调用后,Android 调用doInBackground()而不是 调用。但根据文档onCancelled()onPostExecute()

调用此方法将导致返回onCancelled(Object)后在 UI 线程上调用。调用此方法保证永远不会调用doInBackground(Object[])onPostExecute(Object)

它是Android中的错误吗?

更多观察:

  1. cancel(false)从任一线程调用都按照文档中的说明进行。
  2. cancel(true)从 UI 任务调用不会调用onPostExecute(),也不会抛出InterruptedException在下面的 logcat 跟踪中看到的内容。
  3. cancel(false/true)从任何线程调用有时甚至onCancelled()doInBackground()返回之前调用。这显然违反了文档,其中指出

调用此方法将导致在返回doInBackground(Object[])在 UI 线程上调用 onCancelled(Object) 。

代码:(在 Android 2.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;
}

日志输出

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. 有一个例外,因为您调用 cancel(true) 会向运行 doInBackground() 的线程发送一个中断 - 但是,在这种情况下,您是从 doInBackground() 内部调用 cancel(true),从而导致线程立即发送一个打断自己。

  2. 您的代码在 Android 2 上运行,但您引用了 Android 4 的文档。问题是 cancel() 上的行为在 Android 2 和 Android 4 之间发生了变化。

    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 回答