AsyncTask无法执行onPostExecute。

3
我正在尝试执行以下AsyncTask:
private class TimeUpdateTask extends AsyncTask<List<mObject>, Integer, Void> {

        @Override
        protected Void doInBackground(List<mObject>... params) {
            mObject o;
            int i;
            int numChecked = 0;

            List<mObject> mObjects = params[0];
            while(true)
            {   
                if (isCancelled())
                {
                    Log.w("TAG", "task interrumped");
                    return null;
                }

                    for (i=0 ; i < mObjects.size() ; i++)
                    {
                        o = mObjects.get(i);
                        if (!o.isChecked())
                        {
                            o.calculateProgress();
                            if (o.isChecked())
                            {
                                numChecked++;
                            }
                        }
                    }
                publishProgress(numChecked);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }

            }
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void onProgressUpdate(Integer... param){
            int progressCompleted = param[0];

            ((ArrayAdapter<mObject>) EventListView.this.EventView.getAdapter()).notifyDataSetChanged();

            mMain.setProgressBarCompleted(progressCompleted);
        }

        /*This should execute*/
        @Override
        protected void onPostExecute(Void result) {
            Log.d("TAG","End onPostExecute");
         }

    }

当我在这个任务上调用cancel(false)时,onPostExecute应该被执行,但它从未被执行。
代码有什么问题还是其他原因呢?我看了很多SO中的答案,似乎即使你只使用一个#5 AsyncTask(就像我的情况一样),它还是存在的。

1
除了其他的评论/答案之外 - 不要使用 while(true)。尝试使用 while(!isCancelled()) - 这更有意义。 - Squonk
谢谢,我也是这么想的 :) - Nikoi
3个回答

10

这里有一块重要的内容需要学习。

根据开发者文档(请见下方粗体字):http://developer.android.com/reference/android/os/AsyncTask.html#cancel(boolean

尝试取消此任务的执行。如果该任务已完成、已被取消或由于其他原因无法取消,这次尝试将失败。如果成功,并且在调用 cancel 方法时此任务尚未启动,则此任务不应运行。如果任务已经启动,则 mayInterruptIfRunning 参数决定是否应中断执行此任务的线程以尝试停止任务。

调用此方法将导致在 doInBackground(Object[]) 返回后,在 UI 线程上调用 onCancelled(Object)。 调用此方法保证永远不会调用 onPostExecute(Object)。 在调用此方法之后,您应该定期检查从 doInBackground(Object[]) 返回的 isCancelled() 的值,以尽早完成任务。


谢谢您指出这一点。现在一切都更加清晰了 :) - Nikoi
调用此方法可以保证永远不会调用onPostExecute(Object)方法。这就是为什么原始问题(OP)从未看到调用onPostExecute(...)方法的原因。+1 - Squonk

3

在Android中,当任务被取消时会使用onCancelled()方法,而不会调用onPostExecute()方法!


2
我认为调用cancel实际上会取消所有执行,包括onPostExecute。你应该使用自己的本地布尔变量并这样做:
private boolean shouldContinue = true;

public void customCancel() 
{
       shouldContinue = false;
}

然后在您的循环中执行以下操作:

if (!shouldContinue)
{
    Log.w("TAG", "task interrumped");
    return null;
}

抱歉,这没有任何意义 - 在调用 onCancelled() 方法时,doInBackground(...) 方法已经终止,因此 shouldContinue 在“循环”中已不再相关。 - Squonk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接