AsyncTask onCancelled(Object) 从未在 asyncTask.cancel(true) 之后调用;
Posted
技术标签:
【中文标题】AsyncTask onCancelled(Object) 从未在 asyncTask.cancel(true) 之后调用;【英文标题】:AsyncTask onCancelled(Object) never invoked after asyncTask.cancel(true); 【发布时间】:2016-07-31 10:23:35 【问题描述】:正如文档所说,onCancelled(Object)
应该在以下时间被调用:
cancel(boolean) 被调用并且 doInBackground(Object[]) 已经完成。
在我的AsyncTask
中,我调用了this.cancel(true);
,但从未调用过onCancelled(Object)
方法。
这里只贴相关代码。
MainActivity.java:
AsyncTask.Status asyncTaskStatus = new GethtmlDocument(urlString).execute().getStatus();
异步任务:
private class GetHtmlDocument extends AsyncTask<String,Void,HtmlPage>
private String url;
/**
* Constructor.
*
* @param url Url to parse from in the web.
*/
public GetHtmlDocument(String url)
this.url = url;
@Override
protected void onPreExecute()
Log.d(MainActivity.ASYNC_TASK_TAG, "onPreExecute() called");
@Override
protected HtmlPage doInBackground(String... params)
//android.os.Debug.waitForDebugger();
Log.d(MainActivity.ASYNC_TASK_TAG, "doInBackground() called");
if (this.isCancelled())
return null;
else
HtmlPage htmlPage = new HtmlPage(getParsedDocument(this.url));
return htmlPage;
/**
* Runs on the UI thread after doInBackground().
* The specified result is the value returned by doInBackground().
* This method won't be invoked if the asynchronous task was cancelled.
*
* @param htmlPage
*/
@Override
protected void onPostExecute(HtmlPage htmlPage)
Log.d(MainActivity.ASYNC_TASK_TAG, "onPostExecute() called");
if (htmlPage.getHtmlDocument() != null)
this.cancel(true);
setHtmlPage(htmlPage);
/**
* A task can be cancelled at any time by invoking cancel(boolean).
* Invoking this method will cause subsequent calls to isCancelled() to return true.
* After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns.
* To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
*
* @param htmlPage
*
*/
@Override
protected void onCancelled(HtmlPage htmlPage)
Log.d(MainActivity.ASYNC_TASK_TAG, "onCancelled() called");
我调试了应用程序,我确定this.cancel(true);
在AsyncTask
onPostExecute()
方法中被调用。
【问题讨论】:
【参考方案1】:这仅仅是因为您在 AsyncTask 完成工作后调用了this.cancel(true)
!
意思是,您可以取消 AsyncTask,而它在 doInBackground
中执行其工作,并且在其状态为“完成”之后
来自文档,
可以通过调用
cancel(boolean)
随时取消任务。 调用此方法将导致对isCancelled()
的后续调用 返回真。调用此方法后,onCancelled(Object)
,改为 的onPostExecute(Object)
将在之后调用doInBackground(Object[])
返回。确保任务被取消 你应该尽快检查返回值isCancelled()
定期从doInBackground(Object[])
,如果可能的话 (例如在循环内。)
所以很明显,onCancelled
方法是在 AsyncTask 执行任务时在 doInBackground
完成之前调用的,onCancelled(Object)
显然是为了调用“INSTEAD” onPostExecute
的取消事件。 cancel(true)
method 旨在“中断”AsyncTask 的操作。
还有,我想知道你为什么要取消任务?您可以简单地检查结果是否为 null 并仅在其不为 null 时才执行 onPostExecute,如下所示:
@Override
protected void onPostExecute(HtmlPage htmlPage)
if (htmlPage.getHtmlDocument() != null)
Log.d(MainActivity.ASYNC_TASK_TAG, "onPostExecute() called");
setHtmlPage(htmlPage);
或
@Override
protected void onPostExecute(HtmlPage htmlPage)
Log.d(MainActivity.ASYNC_TASK_TAG, "onPostExecute() called");
if (htmlPage.getHtmlDocument() != null)
return;
setHtmlPage(htmlPage);
【讨论】:
让我解决这个问题。当onPostExecute()
被调用时,AsyncTask
会自然终止吗?
没有。来自 Doc:onPostExecute(Result)
,在后台计算完成后在 UI 线程上调用。 onPostExecute
的执行后,AsyncTask 自然终止。但是你可以控制onPostExecute
来退出,就像返回一样。提供cancel(true)
是为了让您/用户控制异步任务的后台执行,例如如果需要太多时间,我们需要取消它。 cancel(true) 方法提供了在执行后台操作时取消 AsyncTask 的机会。而且,如果你能解释为什么要在onPostExecute
中取消任务,我可以解释更多
@God 如果能解决您的问题,请接受我的回答。谢谢
首先谢谢你。第二 - 我使用Jsoup
来解析doInBackground()
方法中的HTML
页面。问题是解析并不总是成功,因此 htmlPage 对象为空。我想知道doInBackground()
何时成功解析页面,然后将onPostExecute()
中的值分配给HtmlPage
的全局变量,并且不会再次调用doInBackground()
,因此它无法更改全局 HtmlPage
再次为空。
它可以在 onPostExecute 中通过检查 HtmlPage 是否为空并相应地设置一个全局变量来完成。无需取消。并且,如果您在 doinbackground 中执行循环操作,并且如果在任何迭代中 HtmlPage 为空,则需要停止它,那么只需在每次迭代时检查 if(HtmlPage == null)
并检查 return HtmlPage;
是否为真。取消是为了给外部中断。您还有其他措施可以在内部结束操作:-)以上是关于AsyncTask onCancelled(Object) 从未在 asyncTask.cancel(true) 之后调用;的主要内容,如果未能解决你的问题,请参考以下文章
如果超时或无法访问服务器,Fire base 不会调用 onCancelled
Android多线程的四种方式:Handler、AsyncTask、ThreadPoolExector、IntentService
AsyncTask - 等待其他 Asynctask 的执行