AsyncTask取消无效

edi*_*thk 2 multithreading android android-asynctask

我正在学习如何取消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");
Run Code Online (Sandbox Code Playgroud)

"取消1"和"取消2"在logcat上显示正确执行,但当"取消3"试图执行时抛出ActivityThread.performLaunchActivity错误.(在logcat上没有显示取消3)我的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();

    }       
}
Run Code Online (Sandbox Code Playgroud)

Sid*_*ele 13

我的方法略有不同,也许有点冗长.但它一直没有任何问题.

这段代码进入了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
}
Run Code Online (Sandbox Code Playgroud)

你已经Asynctask声明了:MyAsyncTask asyncTask = new MyAsyncTask();.除此之外,还创建了两个实例boolean.打电话给他们,例如:

boolean blMyAsyncTask;
boolean cancelTask;
Run Code Online (Sandbox Code Playgroud)

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

blMyAsyncTask = true;
Run Code Online (Sandbox Code Playgroud)

并在onPostExecute():

blMyAsyncTask = false;
Run Code Online (Sandbox Code Playgroud)

并且,同样onPostExecute(),我在检查状态后也会执行余数函数cancelTask boolean.例如:

if (cancelTask == false)    {
    // THE NORMAL CODE YOU HAVE IN YOUR onPostExecute()
}
Run Code Online (Sandbox Code Playgroud)

最后,在onDestroy()(我使用它,但我怀疑它onPause()也可以工作.从来没有onPause()完全诚实),检查的状态boolean blMyAsyncTask

if (blMyAsyncTask== true)   {
    asyncTask.cancel(true);
}
Run Code Online (Sandbox Code Playgroud)

正如我在开始时所说的那样,它很长,甚至可能很复杂,但它从未失败过.如果你愿意,我也认为这是一个小模块.如果我有更多Asycntasks添加Activity,我可以添加另一个检查onDestroy().