J'exécute des opérations de récupération de fichiers audio et de lecture de fichiers audio à distance dans un thread d'arrière-plan en utilisant AsyncTask
. Une Cancellable
barre de progression s'affiche pour le temps d'exécution de l'opération d'extraction.
Je veux annuler / abandonner l' AsyncTask
exécution lorsque l'utilisateur annule (décide de ne pas) l'opération. Quelle est la manière idéale de gérer un tel cas?
while(running)
parwhile(!isCancelled())
comme d'autres l'ont dit ici dans les commentaires.Si vous faites des calculs :
isCancelled()
périodiquement.Si vous faites une requête HTTP :
HttpGet
ouHttpPost
quelque part (par exemple, un champ public).cancel
, appelezrequest.abort()
. Cela provoqueraIOException
être jeté à l'intérieur de votre fichierdoInBackground
.Dans mon cas, j'avais une classe de connecteur que j'ai utilisée dans diverses AsyncTasks. Pour faire simple, j'ai ajouté une nouvelle
abortAllRequests
méthode à cette classe et j'ai appelé cette méthode directement après l'appelcancel
.la source
HttpGet.abort()
partir d'un fil d'arrière-plan ou vous obtiendrez un fichierandroid.os.NetworkOnMainThreadException
.cancel(true)
interrompre la requête? De la documentation:If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
HttpURLConnection.disconnect();
cancel(true)
. Je l'ai utilisé et ça marche.Le fait est que l'appel AsyncTask.cancel () n'appelle que la fonction onCancel dans votre tâche. C'est là que vous souhaitez traiter la demande d'annulation.
Voici une petite tâche que j'utilise pour déclencher une méthode de mise à jour
la source
running
drapeau. AsyncTask a un indicateur interne qui est défini lorsque la tâche a été annulée. Remplacezwhile (running)
parwhile (!isCancelled())
. developer.android.com/reference/android/os/... Donc, dans ce cas simple, vous n'avez pas besoin deonCancelled()
remplacement.Simple: n'utilisez pas de fichier
AsyncTask
.AsyncTask
est conçu pour des opérations courtes qui se terminent rapidement (dizaines de secondes) et n'ont donc pas besoin d'être annulées. "Lecture de fichier audio" n'est pas admissible. Vous n'avez même pas besoin d'un fil d'arrière-plan pour la lecture de fichiers audio ordinaires.la source
onPostExecute()
pour voir si vous devez continuer le travail.La seule façon de le faire est de vérifier la valeur de la méthode isCancelled () et d'arrêter la lecture lorsqu'elle renvoie true.
la source
C'est ainsi que j'écris mon AsyncTask
le point clé est d'ajouter Thread.sleep (1);
la source
Notre variable de classe globale AsyncTask
Et action KEYCODE_BACK qui interrompent AsyncTask
Ça marche pour moi.
la source
Je n'aime pas forcer d'interrompre
cancel(true)
inutilement mes tâches asynchrones car elles peuvent avoir des ressources à libérer, telles que la fermeture de sockets ou de flux de fichiers, l'écriture de données dans la base de données locale, etc. D'autre part, j'ai été confronté à des situations dans lesquelles le La tâche async refuse de se terminer une partie du temps, par exemple parfois lorsque l'activité principale est en cours de fermeture et que je demande à la tâche asynchrone de se terminer depuis l'intérieur de laonPause()
méthode de l'activité . Il ne s'agit donc pas simplement d'appelerrunning = false
. Je dois opter pour une solution mixte: les deux appellentrunning = false
, puis donnent à la tâche asynchrone quelques millisecondes pour terminer, puis appellent soitcancel(false)
oucancel(true)
.En conséquence, après les
doInBackground()
finitions, laonCancelled()
méthode est parfois appelée, et parfoisonPostExecute()
. Mais au moins la fin de la tâche asynchrone est garantie.la source
En référence à la réponse de Yanchenko du 29 avril '10: Utiliser une approche 'while (running)' est bien lorsque votre code sous 'doInBackground' doit être exécuté plusieurs fois lors de chaque exécution de l'AsyncTask. Si votre code sous 'doInBackground' doit être exécuté une seule fois par exécution de l'AsyncTask, envelopper tout votre code sous 'doInBackground' dans une boucle 'while (running)' n'empêchera pas le code d'arrière-plan (thread d'arrière-plan) de s'exécuter lorsque le AsyncTask lui-même est annulé, car la condition 'while (running)' ne sera évaluée qu'une fois que tout le code à l'intérieur de la boucle while aura été exécuté au moins une fois. Vous devez donc soit (a.) Diviser votre code sous 'doInBackground' en plusieurs blocs 'while (running)' ou (b.) Effectuer de nombreux 'isCancelled'https://developer.android.com/reference/android/os/AsyncTask.html .
Pour l'option (a.), On peut donc modifier la réponse de Yanchenko comme suit:
Pour l'option (b.), Votre code dans 'doInBackground' ressemblera à ceci:
la source