AysncTask取消本身仍调用onPostExecute() [英] AysncTask cancelling itself still calls onPostExecute()
问题描述
调用 AsyncTask.cancel(真)
从内部 doInBackground()
,而不是调用<$ C $后C> onCancelled(),Android的电话 onPostExecute()
。但按照文档:
调用此方法将导致
onCancelled(对象)
被调用 在UI线程doInBackground上(对象[])
的回报。 调用此 方法保证onPostExecute(对象)
则永远不会调用
难道是Android的一个错误?
更多意见:
- 电话
取消(假)
从在指定的任一主题的作品 文档。 - 电话
取消(真)
从UI任务做的没有的通话onPostExecute()
,也不会抛出InterruptedException的
看到在logcat中追踪下文。 - 电话
取消(假/真)
从任何线程有时叫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()
-
有因为调用取消(真),其发送中断运行doInBackground()该线程一个异常 - 然而,在这种情况下,要调用从取消(真)内doInBackground(),因此引起线程立即发送一个中断本身。
-
您$ C $,C是Android的2运行,但你引用的文档为Android 4。问题是,取消()的行为的Android 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 afterdoInBackground(Object[])
returns. Calling this method guarantees thatonPostExecute(Object)
is never invoked.
Is it a bug in Android?
More Observations:
- Calling
cancel(false)
from either thread works as specified in the documentation. - Calling
cancel(true)
from the UI task does not callonPostExecute()
, nor does it throw theInterruptedException
seen in the logcat traces below. - Calling
cancel(false/true)
from any thread sometimes callsonCancelled()
even beforedoInBackground()
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()
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.
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.
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.
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屋!