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:

  • Android: Quitter le Looper?
  • Comment simuler la perte totale de réseau dans Android Emulator
  • Le processus Android produit le message "mort" de Logcat très souvent.
  • Android RecyclerView: Modifiez le fichier de mise en page LIST à GRID onOptionItemSelectionné
  • GetSupportActionBar utilisant FragmentActivity
  • Java.lang.NoClassDefFoundError: com.google.android.gms.R $ styleable 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.

  • Que faire à propos de curl clone.bundle error on AOSP repo sync
  • Comment obtenir un effet de couleur magique comme Cam Scanner en utilisant OpenCV
  • Type d'erreur 3. La classe d'activité {com.awesome_project / com.awesome_project.MainActivity} n'existe pas en mode réactif natif (appareil Android)
  • Plugin Android Gradle 0.7.0: "duplication de fichiers pendant l'emballage d'APK"
  • Émultiplicateur Android http-proxy SSL échec de prise de contact
  • Un émulateur d'Android très faible, existe-t-il une solution?
  • 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.