AsyncTask

 

AsyncTask est une classe permettant le lancement de thread asynchrone en tâche de fond tout en ayant la possibilité d'informer simplement l'UI Thread de l'état d'avancement.

Ces threads doivent donc avoir une fin et ne doivent pas tourner en boucle infinie !

Les avantages:

- Pas besoin de créer ou de terminer le thread en arrière plan.

- Communication Thread en arrière plan/ UI Thread simplifiée.

 

Les méthodes

Comme il s'agit de nous simplifier la vie, AsyncTask met à disposition 4 méthodes dont une obligatoire:

doInBackground(): Il s'agit du traitement qui sera lancé en arrière plan (donc dans un thread). Elle est donc évidemment obligatoire, sinon AsyncTask ne serait pas utile !

Signature: doInBackground(Params...)

onProgressUpdate(): Méthode lancée dans l'UI Thread. Elle permettra d'indiquer l'avancement du traitement en tâche de fond à l'utilisateur. Cette méthode sera déclenchée uniquement en utilisant publishProgress() depuis le code de la méthode doInBackground().

Signature: onProgressUpdate(Progress...)

 

onPreExecute(): Cette méthode est déclenchée depuis l'UI Thread avant le lancement du thread en arrière plan. Elle pourra par exemple permettre l'initialisation d'une progress bar ou avertir l'utilisateur du lancement du traitement en arrière plan.

Signature: onPreExecute()

onPostExecute(): Pour informer de la fin d'un traitement en arrière plan ou pour cacher la progress bar par exemple.

Signature: onPostExecute(Result)

Image non trouvée !onPostExecute() n'est pas systématiquement déclenchée ! Il est en effet possible d'interrompre une tâche en arrière plan. Il n'y aura pas d'appel onPostExecute() mais à onCancelled(Object).

 

Points importants sur les méthodes de AsyncTask

Image non trouvée !Les trois méthodes onProgressUpdate(), onPreExecute() et onPostExecute() s'exécutant sous l'UI thread, elles ne doivent pas effectuer de traitement lourd sous peine d'ANR !

Image non trouvée !Ne jamais lancer la méthode onProgressUpdate directement, toujours passer par publishProgress() ! Même remarque pour les autres méthodes !

 

Création de votre classe de tâches asynchrones

Votre classe devra étendre la classe AsyncTask de la manière suivante

private class MyTask extends AsyncTask<Params, Progress, Result> { ... }

Les types de paramètres des méthodes

Comme vous pouvez le constater, les signatures des méthodes sont plutôt particulières.

Les types de la classes AsyncTask sont en effet génériques. Vous pouvez donc utiliser ce que vous voulez, il suffit de le préciser lors de la déclaration de votre classe.

Les trois types utilisés par AsyncTask sont les suivants:
Params: Type de paramètres qui seront passés à doInBackground()
Progress: Type de paramètres qui seront passés à onProgressUpdate().
Result: Type de paramètres qui seront passés à onPostExecute().

Si vous ne voulez passer aucun paramètre, vous pourrez faire

private class MyTask extends AsyncTask<Void, Void, Void> {

@Override
protected void onPreExecute() {
...
}

@Override
protected void onProgressUpdate(Void... rien){
...

}

@Override
protected Void doInBackground(Void... rien) {

...

}

@Override
protected void onPostExecute(Void rien) {

...

}

}

Si vous voulez passer une liste d'url à récupérer et le % d'avancement:

private class MyTask extends AsyncTask<URL, Integer, Void> {

@Override
protected void onPreExecute() {
...
}

@Override
protected void onProgressUpdate(Interger... pourcentage){

// Afficher le pourcentage

...

}

@Override
protected Void doInBackground(URL... urls) {

int count = urls.length; // Récupérer le nombre d'urls passées

...

}

@Override
protected void onPostExecute(Void rien) {

...

}

}

etc...

 

Où créer, instancier votre classe AsyncTask

Votre classe devra être chargée, instanciée et exécutée depuis un UI Thread !

 

Exécuter votre tâche en arrière plan

Pour exécuter notre tâche en arrière plan, la méthode execute(Params... params) sera utilisée.

Image non trouvée !Il sera possible de lancer plusieurs tâches...

 

Interrompre l'exécution d'une tâche

Il est possible de mettre fin à votre tâche en arrière plan (par exemple, pour traiter la rotation de l'écran qui va détruire l'UI Thread, volontairement (abandon de l'utilisateur), suite à une demande du système d'arrêter votre UI Thread en arrière plan par manque de mémoire).

Dans ce cas, il faut utiliser la méthode cancel(boolean mayInterruptIfRunning).

mayInterruptIfRunning à vrai indique qu'il faut détruire le thread s'il est déjà en cours d'exécution, si le thread n'est pas en cours d'exécution, il ne s'exécutera jamais. A faux, cela signifie que le thread ne pourra jamais démarrer, mais il ne s'arrête pas si déjà en cours d'exécution.

Image non trouvée !On utilisera false si le thread n'est pas conçu pour pouvoir s'interrompre.

Suite à l'invocation de cette méthode, doInBackGround() va s'interrompre (en retournant éventuellement un résultat) mais onPostExecute() ne sera pas exécutée et sera remplacée par un appel à onCancelled().

Image non trouvée !Il peut être intéressant de contrôler la valeur en retour de isCancelled() périodiquement depuis doInBackGround() afin de sortir le plus rapidement possible de cette méthode (et tout spécialement dans les boucles du traitement !).

 

La méthode protected void onCancelled (Result result) est déclenchée lorsque l'UI thread lance un cancel(boolean) et que doInBackground(Object[]) est terminée. result étant la valeur retournée éventuellement par doInBackGround(). Si vous n'utilisez pas cette méthode, alors onCancelled() sera lancée automatiquement (vous n'avez pas à y faire appel !).

Image non trouvée !Il est préférable de surcharger onCancelled (Result result) que onCancelled (), mais tout dépendra de la version de l'API utilisée (à partir de la 11 pour onCancelled (Result result)).

 

Etat de la tâche en arrière plan

La méthode getStatus() retourne l'état de la tâche:

AsyncTask.Status.FINISHED: onPostExecute(Result) a terminé son travail.
AsyncTask.Status.PENDING: indique que le traitement n'a pas encore été démarré
AsyncTask.Status.RUNNING: Le traitement est en cours.

 

Exemple de code

Le source AsyncTaskActivity.java

Ce programme met en oeuvre pas mal de choses:

- Une progress bar afin de voir évoluer notre traitement.

- Un Toggle button ON/OFF pour lancer/interrompre notre tâche de fond (avec un listener sur le bouton).

- Les toasts pour afficher l'avancé globale du traitement.

Puis le fichier layout main.xml

Le fichier Strings.xml

Et le fichier AndroidManifest.xml