Bonjour chers amis développeurs Android ! Aujourd’hui nous allons voir comment fonctionne la classe AsyncTask.

Comme son nom l’indique, une AsyncTask permet de réaliser des tâches de manière asynchrone, à la manière de la classe Thread. L’avantage de l’AsyncTask est sa simplicité d’utilisation et d’implémentation. Le Thread secondaire est créé automatiquement et la communication entre les différents Thread est simplifiée.

Lors du développement d’une application, il faut bien avoir en tête que toutes les tâches consommatrices de ressources (requêtes http, calculs lourds, …) doivent se faire dans un Thread séparé. En effet, le système affiche un message d’erreur et ferme l’application lorsque le Thread principal (appelé UI Thread) est bloqué trop longtemps.

Mise en place du projet

Nous allons donc d’abord créer un nouveau projet appelé AsyncBigCalcul. Nous allons faire en sorte d’effectuer un traitement long de manière asynchrone.
Premièrement, nous allons modifier le layout main.xml en lui ajoutant un Button et une ProgressBar. Le premier servira à lancer le traitement ; la seconde à afficher la progression du traitement.
Voici le code XML, rien de difficile.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:layout_marginTop="10dp"
        android:id="@+id/btnLaunch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Lancer la tâche" />
    
    <TextView        
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Progression de la tâche asynchrone:" />

    <ProgressBar
        android:id="@+id/pBAsync"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_margin="10dp"
        android:layout_height="wrap_content" />    

</LinearLayout>

L’activité principale

Nous allons d’abord récupérer les composants définis dans le layout puis ajouter un listener sur le bouton afin qu’à chaque appui on exécute une nouvelle instance de BigCalcul. Jusque là, rien de bien compliqué encore une fois.

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;

public class AsyncBigCalculActivity extends Activity {

	private ProgressBar mProgressBar;
	private Button mButton;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// On récupère les composants de notre layout
		mProgressBar = (ProgressBar) findViewById(R.id.pBAsync);
		mButton = (Button) findViewById(R.id.btnLaunch);

		// On met un Listener sur le bouton
		mButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				BigCalcul calcul=new BigCalcul();
				calcul.execute();
			}
		});
	}
}

La classe BigCalcul

Passons ensuite à l’écriture de notre classe BigCalcul, qui hérite d’AsyncTask. Ici je l’ai mise en classe privée mais c’est possible de l’écrire à part. Je vous laisse admirer (et essayer de comprendre) le code :

private class BigCalcul extends AsyncTask<Void, Integer, Void>
{

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		Toast.makeText(getApplicationContext(), "Début du traitement asynchrone", Toast.LENGTH_LONG).show();
	}

	@Override
	protected void onProgressUpdate(Integer... values){
		super.onProgressUpdate(values);
		// Mise à jour de la ProgressBar
		mProgressBar.setProgress(values[0]);
	}

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

		int progress;
		for (progress=0;progress<=100;progress++)
		{
			for (int i=0; i<1000000; i++){}
			//la méthode publishProgress met à jour l'interface en invoquant la méthode onProgressUpdate
			publishProgress(progress);
			progress++;				
		}	
		return null;
	}

	@Override
	protected void onPostExecute(Void result) {
		Toast.makeText(getApplicationContext(), "Le traitement asynchrone est terminé", Toast.LENGTH_LONG).show();
	}
}

Explications :
Les trois paramètres attendus lors de la déclaration sont des types génériques dont voici la signification :

  • Le premier est le type des paramètres fournis à la tâche
  • Le second est le type de données transmises durant la progression du traitement
  • Enfin le troisième est le type du résultat de la tâche

Une AsyncTask doit obligatoirement implémenter la méthode doInBackground. C’est elle qui réalisera le traitement de manière asynchrone dans un Thread séparé. Les méthodes onPreExecute (appelée avant le traitement), onProgressUpdate (appelée lorsque vous souhaitez afficher sa progression) et onPostExecute (appelée après le traitement) sont optionnelles. Un appel à la méthode publishProgress permet la mise à jour de la progression. On ne doit pas appeler la méthode onProgressUpdate directement.

NOTE: Attention, ces trois méthodes (onPreExecute, onProgressUpdate et onPostExecute) s’exécutent depuis l’UI Thread ! C’est d’ailleurs grâce à cela qu’elles peuvent modifier l’interface. On ne doit donc pas y effectuer de traitements lourds.

Ce qui donnera :

Le code me parait assez clair donc je ne détaille pas plus. Vous remarquerez juste que le soi-disant BigCalcul n’est en fait qu’une grosse boucle, ça me paraissait plus lisible.

Voilà, j’espère que les AsyncTask n’ont plus de secret pour vous à présent ! N’hésitez pas à poser des questions si vous avez des difficultés d’implémentation. Le code source de l’exemple est disponible ici.

Categories: Tutoriels

22 Responses so far.


  1. amine dit :

    Bonjour,

    Je vous remercie pour ce tuto qui est très clair !

    j’ai une petite question, les AsyncTask sont-ils toujours rattachés à une Activity ? ou on peut le rattacher à un service ?
    J’ai un service qui tourne, et à certain moment (changement de connectivité …) je dois lancer des taches, dois-je utiliser d’autres Services ou je peux utiliser les AsyncTask ?

    Je vous remercie,

  2. Benoît dit :

    Bonjour,

    Merci pour ce tuto très simple et très clair ça m’aide beuacoup !

    Par contre je rencontre un problème et je ne vois trop comment le résoudre. Lorsque je tourne l’écran pendant que l’asynctask s’exécute, la barre de progression s’arrête mais l’asynctask continue son calcul. En effet, j’ai bien le Toast qui dit que le calcul est terminé.

    Comment pourrai-t-on gérer ce cas ?

    Merci

  3. Dimitri dit :

    Moi je j’aimerai bien savoir comment on peut afficher dans l’Activity un return String recupéré depuis le doInBackground

    • Je te conseille de créer une classe privée dérivée d’AsyncTask dans l’activity qui va réaliser la tache souhaitée. Ensuite dans le “onPostExecute()” tu pourras afficher les informations dans l’activity

Leave a Reply


Notifiez-moi des commentaires à venir via email. Vous pouvez aussi vous abonner sans commenter.