AsyncTask取消自身仍调用onPostExecute()

时间:2012-04-15 16:22:06

标签: android android-asynctask

AsyncTask.cancel(true)内拨打doInBackground(),而不是拨打onCancelled(),Android会拨打onPostExecute()。但是as per the documentation

  

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

这是Android中的错误吗?

更多观察结果:

  1. 从任一线程调用cancel(false)按照中指定的方式工作 文档。
  2. 从UI任务调用cancel(true) 调用onPostExecute(),也不会抛出下面的logcat跟踪中的InterruptedException
  3. 即使在cancel(false/true)返回之前,从任何线程调用onCancelled()有时也会调用doInBackground()。这显然违反了文档which states
  4.   

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

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

2 个答案:

答案 0 :(得分:3)

  1. 有一个例外,因为你调用cancel(true)会向运行doInBackground()的线程发送一个中断 - 但是,在这种情况下,你从doInBackground()中调用cancel(true),从而导致线程立即向自己发送中断。

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

    Android 2.3.7 onPostExecute

      

    在doInBackground之后在UI线程上运行。指定的结果是   doInBackground返回的值,如果任务被取消,则返回null   或发生例外。

    Android 4.0.1 onPostExecute

      

    在doInBackground之后在UI线程上运行。指定的结果是   doInBackground返回的值。如果,则不会调用此方法   任务被取消了。

答案 1 :(得分:1)

您应该返回null并在onPostExecute中处理返回。