2013-04-11 5 views
1

J'apprends comment annuler asyncTask donc il n'y a aucune utilisation sur le code ci-dessous.AsyncTask Annuler ne fonctionne pas

J'ai essayé d'appeler le asyncTask et de l'exécuter puis de l'annuler et de l'exécuter.

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

« annuler 1 » et « annuler 2 » est exécuté finement comme indiqué sur logcat mais l'erreur ActivityThread.performLaunchActivity est levée lorsque « cancel 3 » tente d'exécuter. (l'annulation 3 ne s'affiche pas sur logcat) Quelque chose ne va pas avec mon code 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

un bon message sur la façon d'annuler une asynctask http://www.quicktips.in/correct-way-to-cancel-an-asynctask-in-android/ –

Répondre

11

Mon approche est légèrement différente et peut-être un peu longue. Mais cela a toujours fonctionné sans problème.

Ce code va dans doInBackground(). Si vous avez un for... loop, utilisez l'instruction break;. Si vous n'utilisez pas un for.... loop, supprimez-le.

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

Vous avez déjà un Asynctask déclaré: MyAsyncTask asyncTask = new MyAsyncTask();. Avec cela, créez également deux instances de boolean. Appelez-les, par exemple:

boolean blMyAsyncTask; 
boolean cancelTask; 

Maintenant, dans le onPreExecute(), changer l'état de l'instance blMyAsyncTask:

blMyAsyncTask = true; 

Et dans le onPostExecute():

blMyAsyncTask = false; 

Et, dans le même onPostExecute(), je fais aussi les fonctions restantes après avoir vérifié l'état du cancelTask boolean. Par exemple:

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

Enfin, dans le onDestroy() (je l'utilise, mais je soupçonne que le onPause() pourrait travailler aussi.Jamais fait dans le onPause() en toute honnêteté), vérifier l'état de la boolean blMyAsyncTask

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

Comme je l'ai dit au début, il est long, peut-être même compliqué, mais il n'a jamais échoué. Je pense aussi à cela comme un petit modulaire si vous voulez. Si j'ai plus Asycntasks ajouté au Activity, je peux ajouter une autre vérification dans le onDestroy().

+1

+1 pour votre réponse agréable et détaillée :) – edisonthk

+0

@edisonTHK: Merci. Content que je puisse être utile. Au fait, ça marche maintenant? –

0

Pour annuler une tâche asynchrone, appelez la ligne ci-dessous. OnCancelled() est une méthode de remplacement qui est exécutée quand une annulation est appelée.

asyncTask.cancel(); 

3

vous ne devriez pas appeler directement asyncTask.onCancelled();. Vous pouvez appeler cancel(true) et à l'intérieur de votre doInBackground() vous vérifiez isCancelled().

0

Vous pouvez utiliser

asynctask.cancel(true); 

ou

asyncTask.wait(); 

"true" si le thread exécutant cette tâche doit être interrompue; sinon, les tâches en cours sont autorisées

Questions connexes