2013-04-11 2 views
1

Я изучаю, как отменить 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"); 

«отменить 1» и «отменить 2» выполнена точно, как это показано на LogCat но ошибка ActivityThread.performLaunchActivity выбрасывается при «отменить 3» пытается выполнить. (отмена 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(); 

    }  
} 
+0

хорошее сообщение о том, как отменить асинтаску http://www.quicktips.in/correct-way-to-cancel-an-asynctask-in-android/ –

ответ

11

Мой подход немного отличается и, возможно, немного длинный. Но он всегда работал без каких-либо проблем.

Этот фрагмент кода размещен в 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();. Вместе с тем, также создайте два экземпляра 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().

+1

+1 для вашего приятного и подробного ответа :) – edisonthk

+0

@edisonTHK: Спасибо. Рад, что я могу помочь. Кстати, работает ли он сейчас? –

0

Чтобы отменить вызов AsyncTask, выполните следующую строку.

asyncTask.cancel(); 

onCancelled() - метод переопределения, который выполняется, когда вы вызываете отмену.

3

Вы не должны звонить напрямую asyncTask.onCancelled();. Вы можете позвонить cancel(true) и внутри вашего doInBackground() вы проверяете на isCancelled().

0

Вы можете использовать либо

asynctask.cancel(true); 

или

asyncTask.wait(); 

"истина", если поток выполнения этой задачи должно быть прервано; в противном случае завершающиеся задачи могут быть завершены

Смежные вопросы