android – AysncTask取消自身仍调用onPostExecute()

从doInBackground()中调用AsyncTask.cancel(true)后,Android调用onPostExecute(),而不是调用onCancelled().但是 as per the documentation

Calling this method will result in onCancelled(Object) being invoked
on the UI thread after doInBackground(Object[]) returns. Calling this
method guarantees that onPostExecute(Object) is never invoked
.

这是Android中的错误吗?

更多观察:

>从任一线程调用cancel(false)按照中的规定工作
文档.
>从UI任务调用cancel(true)不会调用onPostExecute(),也不会抛出下面的logcat跟踪中看到的InterruptedException.
>甚至在doInBackground()返回之前,从任何线程调用cancel(false / true)有时会调用onCancelled().这显然违反了文档which states

Calling this method will result in onCancelled(Object) being invoked
on the UI thread after doInBackground(Object[]) returns.

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

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()

解决方法

>有一个例外,因为你调用cancel(true),它向运行doInBackground()的线程发送一个中断 – 但是,在这种情况下,你从doInBackground()中调用cancel(true),从而导致线程立即发送对自己的中断.
>您的代码在Android 2上运行,但您引用的是Android 4的文档.问题是在Android 2和Android 4之间,cancel()上的行为发生了变化.

Android 2.3.7 onPostExecute

Runs on the UI thread after doInBackground. The specified result is
the value returned by doInBackground or null if the task was cancelled
or an exception occured.

Android 4.0.1 onPostExecute

Runs on the UI thread after doInBackground. The specified result is the value returned by doInBackground. This method won’t be invoked if the task was cancelled.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...