Les AsyncTask
Une AsyncTask permet de réaliser des tâches de
manière asynchrone (en arrière plan). L’avantage de l’AsyncTask est
sa simplicité d’utilisation et d’implémentation.
Le Thread (processus) secondaire est créé automatiquement et la
communication entre les différents Thread est simplifiée.
Lors du développement
d’une application, à fortiori sous Android car les appareils
fonctionnant sous cet environnement sont souvent "légers", toutes
les tâches consommatrices de ressources (requêtes http (donc
consommation de webservice), calculs lourds, …) doivent se faire
dans un Thread séparé. Sinon, 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
Illustration à partir d'un projet Android appelé
AsyncBigCalcul qui effectue un traitement long de
manière asynchrone. En fait, une énorme boucle.
Premièrement, modification du layout main.xml en
modifiant le contenu du TextView initial ("Progression de la
tâche asynchrone" au lieu de "Hello World") et en ajoutant un
Button et une ProgressBar. Le premier servira à lancer le
traitement ; la seconde à afficher la progression du
traitement. Voici le code XML généré, après modification
:
<?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
Comme habituellement, on récupère les composants définis dans le layout puis on ajoute un écouteur (listener) sur le bouton afin qu’à chaque clic on exécute une nouvelle instance de BigCalcul qui est la classe asynchrone (exécutée en tâche de fond donc).
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;
/** Appelé quand l'activité est créée */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// On récupère les composants du layout
mProgressBar = (ProgressBar) findViewById(R.id.pBAsync);
mButton = (Button) findViewById(R.id.btnLaunch);
// On met un écouteur sur le bouton
mButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
BigCalcul calcul=new BigCalcul();
calcul.execute();
}
});
}
}
La classe BigCalcul
(classe asynchrone)
La classe asynchrone BigCalcul hérite impérativement
d’AsyncTask. Elle est ici en classe privée mais elle aurait
pu être écrite à part. Seule la méthode doInBackGround doit
être obligatoirement redéfinie :
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 :
· Le
1er est le type des paramètres fournis à la tâche (ici
aucun paramètre transmis è Void)
· Le
2nd est le type de données transmises durant la
progression du traitement (ici int)
· Enfin le
troisième est le type du résultat de la tâche (ici aucun résultat
transmis è Void)
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 peut 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 :


