异步任务取消不起作用 [英] AsyncTask Cancel is not working

查看:18
本文介绍了异步任务取消不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am learning how to cancel asyncTask so there is no uses on the code below.

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

I tried to called the asyncTask and execute it then cancel it and execute it.

        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 代码有问题吗?

"cancel 1" and "cancel 2" is executed finely as it shown on logcat but ActivityThread.performLaunchActivity error is thrown when "cancel 3" is trying to execute. (cancel 3 is not showing on logcat) Anything wrong with my asyncTask code?

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

    }       
}

推荐答案

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

My approach is slightly different and perhaps, a little lengthy. But it has always worked without any issues.

这段代码在 doInBackground() 中.如果其中有 for... 循环,请使用 break; 语句.如果您不使用 for.... 循环,请将其删除.

This piece of code goes in the doInBackground(). If you have a for... loop in it, then use the break; statement. If you do not use a for.... loop, remove it.

// 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
}

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

You already have an Asynctask declared: MyAsyncTask asyncTask = new MyAsyncTask();. Along with that, also create two instances of boolean. Call them, for example:

boolean blMyAsyncTask;
boolean cancelTask;

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

Now, in the onPreExecute(), toggle the status of the blMyAsyncTask instance:

blMyAsyncTask = true;

onPostExecute()中:

blMyAsyncTask = false;

而且,在同一个onPostExecute()中,我还在检查cancelTask​​ boolean的状态后执行余数函数.例如:

And, in the same onPostExecute(), I also do the remainder functions after checking the state of the cancelTask boolean. For example:

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

最后,在 onDestroy()(我使用这个,但我怀疑 onPause() 也可以工作.从来没有在 onPause() 老实说),检查 boolean blMyAsyncTask

Finally, in the onDestroy() (I use this, but I suspect the onPause() could work too. Never done it in the onPause() in all honesty), check the status of the boolean blMyAsyncTask

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

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

As I said at the start, it is lengthy, perhaps even complicated, but it has never failed. I also think of this as a little modular if you would. If I have more Asycntasks added to the Activity, I can add another check in the onDestroy().

这篇关于异步任务取消不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆