Chapitre 3.1: Thread, AsyncTask et Handler

Android: A Complete Course

Image non disponible

Android2ee


La Formation et l'Expertise Android à votre service


CommeAirFrance, Orange,Capgemini, Atos WorldLine et bien d'autres.
Vous aussi,
Bénéficiez des meilleures formations Android du moment


Cet article est extrait du livre « Android, A Complete Course », disponible sur Android2ee.com.

Les exemples ou les programmes présents dans cet ouvrage sont fournis pour illustrer les descriptions théoriques. Ce code est libre de toute utilisation, mais n'est pas distribuable.

La distribution du code est réservée au site :

http://android2ee.com.

La propriété intellectuelle du code appartient à :

Mathias Séguy.

ISBN : 979-10-90388-00-0

Copyright © 2011 by Mathias Séguy






Android2EE est référencé en tant qu'organisme de formation, vous pouvez faire prendre en charge tout ou partie du montant de cette formation par votre OPCA. Les formations Android d'Android2EE sont éligibles au titre duDIF et CIF.

Commentez

Article lu   fois.

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Gérer les activités

I-A. Les threads

Si une activité réagit en plus de cinq secondes, elle sera tuée par l'ActivityManager qui la considérera comme morte. Les IHM de l'activité sont dans un thread qui lui est propre (comme en swing). Plusieurs façons d'interagir entre les threads en arrière-plan et le thread d'IHM sont possibles.

Mais surtout garder toujours en tête qu'aucun traitement ne doit être effectué dans ce thread !

I-A-1. Les handlers

L'handler est associé à l'activité qui le déclare et travaille au sein du thread d'IHM. Ce qui signifie que tout traitement effectué par le handler gèle l'IHM le temps qu'il soit effectué. Il faut donc considérer le handler comme celui qui met à jour l'IHM, le thread qui appelle le handler a en charge le traitement. Le handler ne doit se charger que de mettre à jour l'IHM, tout autre comportement est une erreur de conception.

Un thread communique avec un handler au moyen de messages (ou de runnables, mais ce ne sera pas ici expliqué). Pour cela :

  • le thread récupère l'objet « Message » du pool du handler par handler.obtainedMessage. Cette méthode peut être surchargée de manière à envoyer plus d'informations au handler (en lui passant d'autres paramètres) ;
  • le thread envoie le message au handler en utilisant l'une des méthodes suivantes :

    • sendMessage (envoie le message et le place à la fin de la queue),
    • sendMessageAtFrontOfQueue (envoie le message et le place au début de la queue),
    • sendMessageAtTime (envoie le message au moment donné en paramètre et le place à la fin de la queue),
    • sendMessageDelayed (envoie le message après un temps d'attente passé en paramètre et le place à la fin de la queue) ;
  • le handler doit surcharger sa méthode handleMessage pour répondre aux messages qui lui sont envoyés.

Exemple :

 
Sélectionnez
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ProgressBar android:id="@+id/progress"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

Le code Java :

 
Sélectionnez
/**
 * @author mSeguy
 * @goals This class aims to show how to use handler and thread
 */
public class HandlerTuto extends Activity {
    /**     * The progress bar to update     */
    ProgressBar bar;
    /**     * The progress bar increment stored in the bundle of the handler's message     */
    private final String PROGRESS_BAR_INCREMENT="ProgreesBarIncrementId";
    /**     * The handler that manage the communication from external threads to Gui's thread     */
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int progress=msg.getData().getInt(PROGRESS_BAR_INCREMENT);
            // here, just increment the progress bar
            bar.incrementProgressBy(progress);
            // You can do quick stuff that update the Gui
            
        }
    };
    /**     * An atomic boolean to manage the external thread's destruction     */
    AtomicBoolean isRunning = new AtomicBoolean(false);
    /**     * An atomic boolean to manage the external thread's pausing     */
    AtomicBoolean isPausing = new AtomicBoolean(false);

    // Create the activity
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        // Define the progress bar
        bar = (ProgressBar) findViewById(R.id.progress);
        bar.setMax(210);
    }

    /** Called method when launching the activity */
    public void onStart() {
        super.onStart();
        // initialize the progress bar
        bar.setProgress(0);
        // Thread definition, it could have been done in an external classes
        Thread background = new Thread(new Runnable() {
            /**
             * The bundle exchanged within the message between the tread and the handler
             */
            Bundle messageBundle=new Bundle();
            /**
             * The message exchanged between this thread and the handler
             */
            Message myMessage;
            // Overriden Run method
            public void run() {
                try {
                    // If isRunning is false, the run method will end
                    for (int i = 0; i < 20 && isRunning.get(); i++) {
                        // while on Pause but still alive
                        while (isPausing.get() && (isRunning.get())) {
                            // Make a pause
                            Thread.sleep(1000);
                        }
                        // Sleep one second
                        Thread.sleep(1000);
                        // Send the message to the handler (the handler.obtainMessage is more
                        // efficient that creating a message from scratch)
                        //create a message, the best way is to use that method:
                        myMessage=handler.obtainMessage();    
                        //then, if you want add data to your message (you could use arg0 and arg1 too)
                        messageBundle.putInt(PROGRESS_BAR_INCREMENT, i);
                        myMessage.setData(messageBundle);
                        //then send the message
                        handler.sendMessage(myMessage);
                    }
                } catch (Throwable t) {
                    // just end the background thread
                }
            }
        });
        //Initialize the threadSafe booleans
        isRunning.set(true);
        isPausing.set(false);
        //And launch the thread
        background.start();
    }
    
 /************************************************************************************/
/** Managing life cycle *****************************************************************/ 
/**************************************************************************************/
    //Method called when activity stop
    public void onStop() {
        super.onStop();
        //Update the boolean to kill the thread
        isRunning.set(false);
    }

    /* (non-Javadoc) 
     * @see android.app.Activity#onPause()
     */
    @Override
    protected void onPause() {
        super.onPause();
        //Update the boolean to pause the thread
        isPausing.set(true);
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onResume()
     */
    @Override
    protected void onResume() {
        super.onResume();
        //Update the boolean to resume the thread
        isPausing.set(false);
    }

}

I-B. Suis-je dans le thread de l'IHM ou pas ?

La classe « Activity » possède la méthode runOnUIThread pour lancer un traitement dans le thread de l'IHM.

I-C. La désynchronisation

Depuis la version 1.5 d'Android, l'AsyncTask permet une nouvelle façon d'effectuer des tâches en arrière-plan.

Pour cela :

  • créer une sous-classe d'AsyncTask (elle peut être interne et privée à l'activité) ;
  • redéfinir une ou plusieurs de ces méthodes pour spécifier son travail ;
  • la lancer au moyen de sa méthode « execute ».

La dérivation d'une classe AsyncTask n'est pas triviale, elle est générique et à paramètres variables. Pour la généricité, elle attend trois paramètres :

  • le type de l'information qui est nécessaire au traitement (dans l'exemple URL) ;
  • le type de l'information qui est passé à sa tâche pour indiquer sa progression (dans l'exemple : Integer) ;
  • Le type de l'information passé au code lorsque la tâche est finie (dans l'exemple Long).

Un exemple :

 
Sélectionnez
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
        }
        return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        showDialog("Downloaded " + result + " bytes");
    }
}

Les étapes d'AsynchTask :

doInBackground est la méthode qui s'exécute dans un autre thread. Elle reçoit un tableau

d'objets lui permettant ainsi d'effectuer un traitement en série sur ces objets. Seule cette méthode est exécutée dans un thread à part, les autres méthodes s'exécutent dans le thread de l'IHM.

onPreExecute est appelée par le thread de l'IHM avant l'appel à doInBackground, elle permet de préinitialiser les éléments de l'IHM.

onPostExecute est appelée lorsque la méthode doInBackground est terminée.

onProgressUpdate est appelée par la méthode publishProgress à l'intérieur de la méthode doInBackground.

Image non disponible

Exemple :

 
Sélectionnez
/**
 * @author mathias seguy
 * @goals This class aims to show a simple usage of the AsyncTask
 */
public class AsyncTuto extends Activity {
    /**    * The progress bar to update     */
    ProgressBar bar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // Define the progress bar
        bar = (ProgressBar) findViewById(R.id.progress);
        bar.setMax(210);
        // Launch the asynchTask
        new MyAsyncTask().execute();
    }

    /**
     * This class aims to show a simple derivation of the AsyncTask
     */
    class MyAsyncTask extends AsyncTask<Void, Integer, String> {
        /**     * A simple counter */
        Integer count = 0;

        // override of the method doInBackground (the one which is running in a separate thread)
        @Override
        protected String doInBackground(Void... unused) {
            try {
                while (count < 20) {
                    //increment the counter
                    count++;
                    // Make a pause
                    Thread.sleep(1000);
                    //talk to the onProgressUpdate method
                    publishProgress(count);
                }
            } catch (InterruptedException t) {
                // just end the background thread
                return ("The sleep operation failed");
            }
            return ("return object when task is finished");
        }

        // override of the onProgressUpdate method (runs in the GUI thread)
        @Override
        protected void onProgressUpdate(Integer... diff) {
            bar.incrementProgressBy(diff[0]);
        }

        // override of the onPostExecute method (runs in the GUI thread)
        @Override
        protected void onPostExecute(String message) {
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
        }
    }
}

I-D. AsyncTask ou handler

Ces deux méthodes ont pour but d'effectuer des traitements liés aux IHM dans des threads indépendants de ceux de l'IHM. La question est de savoir laquelle choisir et dans quelle circonstance.

L'idée est que si vous faites un traitement lourd, spécifique, qui n'a besoin que de donner son avancement et sa fin (typiquement charger des données), le mieux est l'utilisation de l'AsyncTask. A contrario, si vous avez besoin d'établir une communication avec l'IHM, il est plus pertinent d'utiliser un handler (l'exemple de la communication Bluetooth entre deux appareils utilise ce pattern).

II. Android2EE: La Formation et l'Expertise Android à votre service

Image non disponible

Android2EE


Android2EE espère que cet article vous a été utile et profitable.
En tant qu'experts et formateurs sur le développement Android, nous serions heureux de vous accueillir à nos formations pour pouvoir continuer à vous expliquer l'art du développement Android (nous avons des tonnes de choses à vous raconter). Nous sommes persuadés qu'elles sont excellentes, les stagiaires qui les ont suivies le sont aussi.
Alors si vous souhaitez devenir un excellent développeur Android, il ne vous reste plus que deux choses à faire:

  • nous envoyer un mail à
  • convaincre votre service R.H. de l'importance de cette formation pour vous et pour l'entreprise.



Pour plus de renseignements, n'hésitez pas à cliquer sur les liens ci-dessous.



Comme AirFrance , Orange, Capgemini , Atos WorldLine et bien d'autres.
Vous aussi,
Bénéficiez des meilleures formations Android du moment



Android2EE est référencé en tant qu'organisme de formation, vous pouvez faire prendre en charge tout ou partie du montant de cette formation par votre OPCA. Les formations Android d'Android2EE sont éligibles au titre du DIF et CIF.

III. Récupération des tutoriels et lecture des autres chapitres du livre

Vous pouvez lire l'ensemble de l'ouvrage sur Android2EE, à cet adresse Livre en consultation. Les 28 chapitres sont disponibles. Un tutorial sera bientôt disponible sur le site Android2EE.

IV. Articles, conférences et autres tutoriaux made in Android2EE

Vous pouvez trouver d'autres articles sur developpez.com rédigés par Android2EE.

Vous pouvez trouver les projets Android open sources d'Android2EE sur GitHub.

Android2EE sur Github

GDirectionsApiUtils pour vous simplifiez l'utilisation du service REST Google Api Direction (les itinéraires entre deux points).

Le MythicServiceHelper est un projet simplifiant la communication entre les services et les activités. Il est mieux d'utiliser, à l'heure d'aujourd'hui, EventBus ou Otto. Vous pouvez aller le voir quand même par curiosité.

Le Bluetooth avec Android expliqué. Ce projet est un chat bluetooth qui vous montre, par l'exemple, comment mettre en place une communication BlueTooth entre deux appareils Android.

Le projet ForecastYahooRest a pour objectif de vous expliquer comment mettre une architecture saine pour vos projets Android pour effectuer des appels REST. Ce projet est lié à la conférence "An Android Journey" que vous pouvez retrouver sur Android2ee.

Le projet SignInWithGoogleTutorialvous explique comment mettre l'authentification Google au sein de vos applications. Il est lié à la conférence Google Sign In que vous pouvez retrouver sur Android2EE.

Vous pouvez trouver les supports des conférences d'Android2EE sur SlideShared.

Android2EE sur SlideShare

Retrouvez la liste des tutoriaux Android2EE de la formation complète. C'est pas ma meilleure conférence :)

An Android Journey La conférence 2014 d'Android2EE qui vous donne toutes les astuces, les bonnes pratiques et les bons conseils à mettre en place dans vos applications pour en faire des applications exceptionnelles.

ActionBarCompat Cette conférence vous explique comment mettre en place l'ActionBar dans vos applications pour toutes les versions du système en utilisant l'ActionBarCompat.

GoogleSignIn L'authentification Google vous est expliquée dans cette conférence.

Android ProTips Cette conférence a été donnée à la DroidCon Paris 2013 pour vous présenter les meilleurs conseils sur le développement Android donnée aux GoogleIo. Ce sont mes bonnes pratiques favorites.

Architecture Android Une peu d'architecture, ça vous dit? Cette conférence est dédiée à l'architecture, quels sont les problèmes rencontrés et les bonnes pratiques à mettre en place.

Android, un nouveau futur s'ouvre à nous Cette conférence, donnée à Brazzaville, présente les enjeux de la mobilité et en particulier ma vision du futur relative à Android.

Combining the power of Eclipse with Android Cette conférence, donnée à l'EclipseDay 2012, présente comment utiliser la DDMS et chasser les fuites mémoires au sein de vos applications Android.

A Quick OverviewCette conférence, donnée au CocoHeads Toulouse en 2012, est une introduction à la programmation Android.

Android A Quick Course @DevoxxFr Cette présentation est un extraie de la conférence "Android A Quick Course", donnée à DevoxxFrance, pour apprendre le développement Android. Les vidéos (3 heures tout de même sont disponibles sur le site Android2EE ou sur Parleys)

Les vidéos de certaines de ces conférences sont disponibles à l'adresse suivante : Les vidéos


V. Le site Android2ee, une référence pour le développement Android.

Le site Android2EE vous propose des tutoriels, des articles, des vidéos, des conférences, des eBooks en libre consultation pour monter en compétence sur la technologie Android.

Vous trouverez tout cela dans la partie « Open Resources ».

N'hésitez plus visitez-le ! Android2EE

VI. Android2ee vous présente l'Ebook de programmation Android

Le nouveau système d'exploitation de Google pour les téléphones portables et les nouvelles tablettes est là. Sa réputation est solide, il envahit le monde de la téléphonie, il est ouvert et offre des outils de développement Java au monde des programmeurs. Il ouvre les portes du développement mobile à tous les développeurs objets avec un coût minime pour la montée en compétence. Une seule question se pose :

Êtes-vous prêts ?

L'objectif de ces livres est très clair : vous permettre en un temps record d'être autonome en programmation Android. Si vous êtes un programmeur Java (débutant ou confirmé), le but est que vous soyez autonome en moins de dix jours. C'est cet objectif qui est à l'origine de ce livre, permettre aux collaborateurs de mon entreprise de monter en compétence sur cette technologie avec rapidité et efficience. Vous serez alors à même de concevoir une application, de l'implémenter, de la tester, de l'internationaliser et de la livrer à votre client.

Lancez-vous dans la programmation Android et faites-vous plaisir !

Vous serez aussi capable de connaître et comprendre quelles sont les considérations à avoir lorsque l'on a à charge une application Android en tant que professionnel de l'informatique. Quelle est la stratégie de tests à utiliser ? Comment signer son application ? Comment la déployer ? Comment mettre en place la gestion du cycle de vie de l'application ? Comment implémenter l'intégration continue ?

Soyez efficient dans l'encadrement de vos projets Android d'entreprise.


L'achat d'un EBook vous donne accès à l'ensemble des tutoriaux Android2EE, plus de 50 projets Android qui vous apprendrons à mettre en place une notion spécifique (SlidingDrawer, Parsing d'un service REST, Mise en place d'un service, d'un ContentProvider...). Vous pouvez dès maintenant vous lancer dans la programmation Android, n'hésitez pas faîtes vous plaisir, il y a 75% de réduction sur les EBooks en ce moment:

Apprendre la programmation Android avec les EBooks Android2EE

Android, A Complete Course, From Basics To Enterprise Edition (fr).

Android, A Quick Course (fr).

Android, An Entreprise Edition Vision (fr).

Les eBooks sont disponibles en français et en anglais, à votre convenance.


Nota Bene: l'ouvrage "Android, A Complete Course, From Basics To Enterprise Edition" réunit, au sein d'un même document, les livres "Android, A Quick Course" et "Android, An Enterprise Edition Vision" permettant au lecteur d'avoir dans un même document la totalité des préoccupations liées à la mise en place de projets Android, de la montée en compétence en tant que développeur à la gestion du cycle de vie du projet.

VII. Remerciements

Nous remercions milkoseck pour sa relecture orthographique.

N'hésitez pas à commenter cet article ! Commentez Donner une note à l'article (0)

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2014 Mathias Seguy. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.