异步任务取消不起作用

4

我正在学习如何取消异步任务,以便不使用下面的代码。

我尝试调用异步任务并执行它,然后取消它并重新执行它。

        MyAsyncTask asyncTask = new MyAsyncTask();
        Log.i("cancel","cancel 1");     
        asyncTask.execute();
        Log.i("cancel","cancel 2");
        asyncTask.onCancelled();
        Log.i("cancel","cancel 3");
        asyncTask.execute();
        Log.i("cancel","cancel done");

"

“取消1”和“取消2”在logcat上展示为执行成功,但是当尝试执行“取消3”时却抛出了ActivityThread.performLaunchActivity错误。(取消3未在logcat上显示) 我的asyncTask代码有问题吗?

"
private class MyAsyncTask extends AsyncTask<String,Integer,Void>{

    private ArrayList<Map<String, String>> list;
    private ProgressBar progressBar;
    @Override
    protected Void doInBackground(String... arg0) {

        progressBar = (ProgressBar)findViewById(R.id.year_expense_progressbar);
        progressBar.setVisibility(View.VISIBLE);
        getListView().setVisibility(View.GONE);
        textView.setVisibility(View.GONE);

        list = new ArrayList<Map<String, String>>();

        String time = "";
        String category = "";
        String expense = "";
        String day = "";
        String month = "";


        totalExpense = 0;       


        Cursor c = SQLLiteAdapter.fetchAllItems();

        while(c.moveToNext() != false){

            if(isCancelled()){
                Log.e("cancel","cancel inside background");
                break;
            }


            // if there is nothing is input, don't execute verifyLevel
            if(tokenizedResult.isEmpty()) break;


            category = c.getString(c.getColumnIndex(SQLLiteAdapter.col_category));
            expense = c.getString(c.getColumnIndex(SQLLiteAdapter.col_price));
            time = c.getString(c.getColumnIndex(SQLLiteAdapter.col_time));
            day = c.getString(c.getColumnIndex(SQLLiteAdapter.col_day));
            month = c.getString(c.getColumnIndex(SQLLiteAdapter.col_month));


            VerifyLevel a = new VerifyLevel(tokenizedResult,category,expense,time,day,month); 
            if(!a.isEmpty()){
                list.add(a.addToList());
            }           

            totalExpense += a.totalExpense;          
        }



        return null;
    }

    @Override
    protected void onPostExecute(Void result)
    {
        progressBar.setVisibility(View.GONE);
        getListView().setVisibility(View.VISIBLE);
        textView.setVisibility(View.VISIBLE);
        fillData(list);
        textView.setText("Total Expense is "+convertNumeric(totalExpense));         
        Log.i("yearExpense","buildList is finished");

    }

    @Override
    protected void onCancelled(){
        super.onCancelled();
        list.clear();
        progressBar.setVisibility(View.GONE);
        totalExpense = 0;
        Log.i("yearEx","Cancel asyncTask");
        Toast.makeText(getApplicationContext(), "cancelled", Toast.LENGTH_SHORT).show();

    }       
}

一个关于如何取消异步任务的好帖子 http://www.quicktips.in/correct-way-to-cancel-an-asynctask-in-android/ - Deepak Swami
4个回答

14

我的方法略有不同,可能有点冗长。但它总是能够正常工作。

这段代码放在doInBackground()中。如果您在其中使用了for...loop,则使用break;语句。如果您没有使用for...loop,请将其删除。

// CHECK IF THE USER HAS CANCELLED THE TASK
if (isCancelled())  {
    cancelTask = true; // (OPTIONAL) THIS IS AN ADDITIONAL CHECK I HAVE USED. THINK OF IT AS A FAIL SAFE.
    break; // REMOVE IF NOT USED IN A FOR LOOP
}

您已经声明了一个AsyncTaskMyAsyncTask asyncTask = new MyAsyncTask();。除此之外,还需要创建两个boolean实例。例如,将它们命名为:

boolean blMyAsyncTask;
boolean cancelTask;

现在,在 onPreExecute() 中,切换 blMyAsyncTask 实例的状态:

blMyAsyncTask = true;

然后在onPostExecute()方法中:

blMyAsyncTask = false;

在相同的onPostExecute()中,我还会检查cancelTask Boolean的状态后执行剩余的功能。例如:

if (cancelTask == false)    {
    // THE NORMAL CODE YOU HAVE IN YOUR onPostExecute()
}

最后,在 onDestroy() 方法中(我使用这个方法,但我认为 onPause() 也可以。老实说,我从来没有在 onPause() 中做过),检查 boolean blMyAsyncTask 的状态。

if (blMyAsyncTask== true)   {
    asyncTask.cancel(true);
}

就像我一开始所说的那样,这可能会很冗长,甚至复杂,但它从未失败过。如果您愿意,我还将其视为一个小型模块化。如果我在Activity中添加了更多的AsyncTasks,我可以在onDestroy()中再添加另一个检查。


@edisonTHK:谢谢。很高兴能帮上忙。顺便问一下,现在它工作了吗? - Siddharth Lele

3

不应直接调用asyncTask.onCancelled();。可以调用cancel(true),并在doInBackground()中检查isCancelled()


0

要取消 AsyncTask,请调用以下代码。

asyncTask.cancel();

onCancelled() 是一个重写方法,当调用 cancel 时执行。


0
你可以使用以下任一方式
asynctask.cancel(true);

或者

asyncTask.wait();

如果正在执行此任务的线程应该被中断,则为“true”;否则,允许正在进行的任务完成。


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