Android AsyncTask ne s'arrêtera pas lors de l'annulation, pourquoi?

J'ai un AsyncTask que j'ai fermé dans l'événement Activity OnPause du cycle de vie, de sorte qu'il ne fonctionne pas lorsque quelqu'un quitte l'application, mais ça continue malgré tout. J'ai ajouté un certain suivi et cet extrait montre le problème.

Trace.d(TAG,"Task state: " + myTask.getStatus() ); myTask.cancel(true); Trace.d(TAG,"Task state: " + myTask.getStatus() ); 

Les sorties:

  • OnCreate n'est pas appelé Activité
  • Désactiver les messages ANR lors du débogage
  • La mise à jour d'Android 17 semble incompatible avec des bocaux externes
  • Impossible d'éditer des fichiers dans Android Studio
  • Android RuntimeException onCreateDialog n'a pas créé de dialogue pour l'identification
  • Comment obtenir des données de prévisualisation brutes de l'objet Camera au moins 15 images par seconde dans Android?
  •  Task state: RUNNING Task state: RUNNING 

    Pourquoi la méthode cancel () n'a-t-elle aucun effet sur l'état de la tâche? Je remarque que les docteurs disent que la méthode d'annulation "tentera" d'arrêter la tâche, mais dans quelles circonstances échouera-t-elle? La tâche est définitivement exécutée car elle produit la sortie du journal toutes les dix secondes, et comme vous pouvez le voir ci-dessus, son état est renvoyé en cours d'exécution.

    Mise à jour: J'ai ajouté un suivi pour me montrer l'état isCancelled () ainsi que cela change. Donc, l'appel à annuler (vrai) modifie l'état annulé de faux en vrai, mais apparemment n'a pas d'effet sur le statut ou d'arrêt du fil.

  • Libagl alphaPlaneWorkaround messages d'erreur dans LogCat
  • Fichiers de dossier d'accès / données dans Android
  • Impossible de trouver hprof-conv lors du lancement d'Android Device Monitor
  • Comment puis-je créer ColorStateList par programme?
  • Android - Service d'arrière-plan périodique - Conseil
  • Comment configurer dagger + gradle
  • 5 Solutions collect form web for “Android AsyncTask ne s'arrêtera pas lors de l'annulation, pourquoi?”

    Gardez à l'esprit que votre Activité et votre AsyncTask sont deux fils distincts. Donc, même si vous annulez le AsyncTask, le code pour annuler la tâche peut ne pas être exécuté encore! C'est pourquoi vous voyez l'AsyncTask toujours en cours d'exécution même après avoir réparé votre bug. Je ne pense pas que le statut changera jusqu'à doInBackground() que doInBackground() dans votre AsyncTask soit terminé. (Assurez-vous donc que vous vérifiez isCancelled() et que vous isCancelled() tôt quand vous avez été annulé!)

    J'ai creusé plus profondément et je me souviens que mon thread appelait une méthode plutôt mal écrit qui le contenait, produisant un autre fil dans celui que je dois annuler:

     public static void haveASleep(int milliseconds) { try { Thread.sleep(milliseconds); } catch (InterruptedException ie) { Trace.w(TAG,"Sleep interrupted"); } } 

    Donc, ce qui se passait, c'est que le fil AsyncTask appelle cette méthode pour attendre un certain temps, et durant l'heure de sommeil, l'appel de méthode cancel () se produit sur AsyncTask, ce qui provoque une exception dans le thread sleep. Mon code n'a guère capté et absorbé cette exception, au lieu de l'utiliser pour arrêter AsyncTask.

    La solution était de rechercher une exception sur le sommeil, et si elle est lancée, pour quitter le fil de façon silencieuse. L'application fonctionne maintenant comme prévu, MAIS …

    Le statut immédiatement après l'appel de la méthode d'annulation () reste en cours d'exécution, mais je soupçonne que c'est parce que, à ce moment-là, il est encore en cours d'exécution et le système d'exploitation ne l'a pas encore éteint. Je ne sais pas si c'est vrai, mais c'est ma meilleure estimation.

     thread.cancel(true); 

    Définit uniquement une variable dans la classe AsyncTask. Ce que vous devez faire, c'est d'implémenter une boucle dans votre tâche d'arrière-plan si vous ne l'avez pas encore. Ensuite, vérifiez et relâchez la boucle si l'annulation est vraie pour chaque itération.

     @Override protected Void doInBackground(Void... params) { synchronized(this) { for(int i = 0; i < 9000; i++) { if(thread.isCancelled()) break; // do stuff } } } 

    Ensuite, réglez-le pour annuler chaque fois que vous en avez besoin pour arrêter. Il s'arrêtera alors avant l'itération suivante.

     @Override public void onStop() { super.onStop(); thread.cancel(true); } @Override public void onDestroy() { super.onDestroy(); thread.cancel(true); } 

    Même si vous savez comment fonctionne l'annulation, il est très difficile de déterminer dans quel état votre thread sera arrêté. Donc, je suggère de mettre en place votre propre façon sûre d'arrêter votre fil, de sorte que vous serez sûr de savoir dans quel état vous vous arrêtez et vous assurez qu'il n'y a pas de fuites de mémoire, etc. D'autres informations sur comment arrêter un thread dans java en toute sécurité Manière de vérifier ce fil Comment annuler un thread de manière rapide et propre dans java?

    Un autre piège possible pour vérifier si vous rencontrez ce problème:

    Assurez-vous de ne pas lancer deux AsyncTasks.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.