Android AysncTask取消自身仍调用onPostExecute()
从Android AysncTask取消自身仍调用onPostExecute(),android,android-asynctask,Android,Android Asynctask,从doInBackground()中调用AsyncTask.cancel(true)后,Android调用onPostExecute(),而不是调用onCancelled()。但是: 调用此方法将导致调用onCancelled(Object) 在doInBackground(Object[])返回后的UI线程上呼叫此 方法保证从不调用onPostExecute(对象) 这是安卓系统中的一个bug吗 更多观察结果: 从任一线程调用cancel(false)都可以按照 文件 从UI任务调用cance
doInBackground()
中调用AsyncTask.cancel(true)
后,Android调用onPostExecute()
,而不是调用onCancelled()
。但是:
调用此方法将导致调用onCancelled(Object)
在doInBackground(Object[])
返回后的UI线程上呼叫此
方法保证从不调用onPostExecute(对象)
这是安卓系统中的一个bug吗
更多观察结果:
cancel(false)
都可以按照
文件cancel(true)
不会调用onPostExecute()
,也不会抛出下面logcat跟踪中看到的中断异常
cancel(false/true)
有时甚至在doInBackground()
返回之前调用onCancelled()
。这显然违反了文件规定:doInBackground(对象[])之后
返回
代码:(在Android 2.2设备上测试)
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()
您应该返回null并在onPostExecute中处理返回
为什么要从
doInBackground
中取消AsyncTask
?那没有道理。cancel(…)
方法故意允许工作线程之外的代码(换句话说,在UI线程上)停止执行。如果doInBackground
中的代码出于任何原因需要自行终止,那么它只需返回。如果您不希望onPostExecute(…)
由于伪取消而执行某些操作,则返回false
否则返回true
@MisterSquonk,“cancel(…)方法故意允许工作线程之外的代码停止执行。”文档并没有说它只能从UI线程调用。为什么不重用onCancelled()
的现有代码,而不是使用难看的解决方法呢?同意,文档中没有说应该只从UI线程调用它,但这似乎是最合乎逻辑的。我之所以这么说,是因为文档确实说,doInBackground
应该定期检查isCancelled()
,看看它是否需要停止自己的执行(由于调用了cancel
)。如果有doInBackground
调用cancel
是正常的,那么isCancelled()
有什么意义呢?@MisterSquonk,很公平。为什么会有这种人为的怪异行为?此外,我还在“更多观察”下添加了第3点。我一直在查看Android v2.2的AsyncTask
源代码。。。但我想不出答案。我可以看到AsyncTask
使用java.util.concurrent.FutureTask
,这就是引发您发布的异常的原因。不过我现在找不到它的来源。我怀疑某个地方有一个小bug,我同意优雅地使用onCancelled
。也许编写自己版本的AsyncTask
就是答案。
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()