【问题标题】:AsyncTask Cancel is not workingAsyncTask Cancel 不起作用
【发布时间】:2013-04-11 11:10:44
【问题描述】:

我正在学习如何取消 asyncTask,所以下面的代码没有用处。

我尝试调用 asyncTask 并执行它,然后取消它并执行它。

        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");

"cancel 1" 和 "cancel 2" 执行得很好,如 logcat 上所示,但是当 "cancel 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();

    }       
}

【问题讨论】:

标签: android multithreading android-asynctask


【解决方案1】:

我的方法略有不同,也许有点冗长。但它一直都能正常工作。

这段代码在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 中添加了更多Asycntasks,我可以在onDestroy() 中添加另一个检查。

【讨论】:

  • @edisonTHK:谢谢。很高兴我能帮上忙。顺便问一下,现在可以用了吗?
【解决方案2】:

您不应直接致电asyncTask.onCancelled();。您可以致电cancel(true) 并在您的doInBackground() 中检查isCancelled()

【讨论】:

    【解决方案3】:

    要取消 AsyncTask,请调用以下行。

    asyncTask.cancel();
    

    onCancelled() 是一个在调用取消时执行的覆盖方法。

    【讨论】:

      【解决方案4】:

      你可以使用任何一个

      asynctask.cancel(true);
      

      asyncTask.wait();
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-08
        • 2011-05-05
        • 2013-05-20
        • 1970-01-01
        • 2016-08-29
        • 1970-01-01
        相关资源
        最近更新 更多