3

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

「キャンセル 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();

    }       
}
4

4 に答える 4

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
}

すでにAsynctask宣言されています: MyAsyncTask asyncTask = new MyAsyncTask();。それに伴い、 のインスタンスも 2 つ作成します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);
}

最初に言ったように、それは長く、おそらく複雑でさえありますが、失敗したことはありません. もしそうなら、私はこれを少しモジュール化したものと考えています。にさらにAsycntasks追加した場合はActivity、 に別のチェックを追加できonDestroy()ます。

于 2013-04-11T11:36:23.637 に答える
3

asyncTask.onCancelled();直接電話してはいけません。を呼び出しcancel(true)て、内部でdoInBackground()をチェックできますisCancelled()

于 2013-04-11T11:13:54.407 に答える
0

AsyncTask をキャンセルするには、以下の行を呼び出します。

asyncTask.cancel();

onCancelled() は、キャンセルが呼び出されたときに実行されるオーバーライド メソッドです。

于 2013-04-11T11:13:08.247 に答える
0

どちらでも使用できます

asynctask.cancel(true);

また

asyncTask.wait();

このタスクを実行するスレッドを中断する必要がある場合は「true」。それ以外の場合、進行中のタスクは完了できます

于 2013-04-11T11:18:41.610 に答える