AysncTask取消本身仍调用onPostExecute() [英] AysncTask cancelling itself still calls onPostExecute()

查看:237
本文介绍了AysncTask取消本身仍调用onPostExecute()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

调用 AsyncTask.cancel(真)从内部 doInBackground(),而不是调用<$ C $后C> onCancelled(),Android的电话 onPostExecute()。但按照文档

  

调用此方法将导致 onCancelled(对象)被调用   在 UI线程doInBackground上(对象[])的回报。 调用此   方法保证 onPostExecute(对象)则永远不会调用

难道是Android的一个错误?

更多意见:

  1. 电话取消(假)从在指定的任一主题的作品 文档。
  2. 电话取消(真)从UI任务做的没有的通话 onPostExecute(),也不会抛出 InterruptedException的看到在logcat中追踪下文。
  3. 电话取消(假/真)从任何线程有时叫 onCancelled()之前 doInBackground()的回报。这显然​​是违反了文件,其中规定的:
  

调用此方法将导致onCancelled(对象)被调用   在UI线程 doInBackground(对象[])返回

code:(测试Android 2.2的设备)

 保护无效doInBackground(虚空...... PARAMS){
    Log.d(TAG,开始doInBackground());
    而(!isCancelled()){
        布尔RET =取消(真);
        Log.d(TAG,取消()返回+ RET);
    }
    Log.d(TAG,从doInBackground()返回);
    返回null;
}
 

logcat的输出

  04-15 21:38:55.519:D / MyTask的(27597):开始doInBackground()
04-15 21:38:55.589:W / AsyncTask的(27597):java.lang.InterruptedException
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1254)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.FutureTask中$ Sync.innerGet(FutureTask.java:219)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.FutureTask.get(FutureTask.java:82)
04-15 21:38:55.589:W / AsyncTask的(27597):在android.os.AsyncTask $ 3.done(AsyncTask.java:196)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.FutureTask中$ Sync.innerCancel(FutureTask.java:293)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.FutureTask.cancel(FutureTask.java:75)
04-15 21:38:55.589:W / AsyncTask的(27597):在android.os.AsyncTask.cancel(AsyncTask.java:325)
04-15 21:38:55.589:W / AsyncTask的(27597):在com.example.test.TestActivity $ MyTask.doInBackground(TestActivity.java:31)
04-15 21:38:55.589:W / AsyncTask的(27597):在com.example.test.TestActivity $ MyTask.doInBackground(TestActivity.java:1)
04-15 21:38:55.589:W / AsyncTask的(27597):在android.os.AsyncTask $ 2.call(AsyncTask.java:185)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.FutureTask.run(FutureTask.java:137)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:561)
04-15 21:38:55.589:W / AsyncTask的(27597):在java.lang.Thread.run(Thread.java:1096)
04-15 21:38:55.589:D / MyTask的(27597):取消()返回:真
04-15 21:38:55.589:D / MyTask的(27597):从doInBackground返回()
04-15 21:38:55.659:D / MyTask的(27597):onPostExecute()
 

解决方案
  1. 有因为调用取消(真),其发送中断运行doInBackground()该线程一个异常 - 然而,在这种情况下,要调用从取消(真)内doInBackground(),因此引起线程立即发送一个中断本身。

  2. 您$ C $,C是Android的2运行,但你引用的文档为Android 4。问题是,取消()的行为的Andr​​oid 2和Android 4之间变化。

    <一个href="http://grep$c$c.com/file/repository.grep$c$c.com/java/ext/com.google.android/android/2.3.7_r1/android/os/AsyncTask.java#AsyncTask.onPostExecute%28java.lang.Object%29"相对=nofollow>安卓2.3.7 onPostExecute :

      

    运行doInBackground后在UI线程上。指定的结果是   通过doInBackground返回的值或空,如果任务被取消   或异常发生。

    <一个href="http://grep$c$c.com/file/repository.grep$c$c.com/java/ext/com.google.android/android/4.0.1_r1/android/os/AsyncTask.java#AsyncTask.onPostExecute%28java.lang.Object%29"相对=nofollow>安卓4.0.1 onPostExecute :

      

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

After calling AsyncTask.cancel(true) from within doInBackground(), instead of calling onCancelled(), Android calls onPostExecute(). But 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.

Is it a bug in Android?

More Observations:

  1. Calling cancel(false) from either thread works as specified in the documentation.
  2. Calling cancel(true) from the UI task does not call onPostExecute(), nor does it throw the InterruptedException seen in the logcat traces below.
  3. Calling cancel(false/true) from any thread sometimes calls onCancelled() even before doInBackground() returns. This is clearly in violation of the documentation, which states:

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

Code: (Tested on Android 2.2 device)

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 output

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

解决方案

  1. There is an exception because you call cancel(true) which sends an interrupt to the thread running doInBackground() - however, in this case, you are calling cancel(true) from within doInBackground(), thus causing the thread to immediately send an interrupt to itself.

  2. Your code is running on Android 2 but you are quoting the docs for Android 4. The problem is that the behaviour on cancel() changed between Android 2 and Android 4.

    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.

这篇关于AysncTask取消本身仍调用onPostExecute()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆