IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Thread, Handler, AsyncTask et fuites mémoires

Image non disponible
Android2EE

Image non disponible

Android2ee


La Formation et l'Expertise Android à votre service


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


Cet article explique comment mettre en place des Threads de background de manière appropriée sous Android. Il explique comment effectuer des traitements dans vos applications. Le discours se centre sur les activités ayant à effectuer des traitements, mais ces principes s'appliquent aussi bien aux services.




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.

5 commentaires

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

0. Introduction

Cet article explique comment mettre en place des Threads de background de manière appropriée sous Android. Il explique comment effectuer des traitements dans vos applications. Le discours se centre sur les activités ayant à effectuer des traitements, mais ces principes s'appliquent aussi bien aux services.

La première partie de cet article explique le fonctionnement des Handlers et des AsyncTasks de manière générale. Elle montre comment déclarer une Thread de traitement et la faire communiquer avec votre Thread d'IHM.

La seconde partie se concentre sur la problématique des fuites mémoires qui apparaissent si la Thread n'est pas liée au cycle de vie de l'activité (du service). Et oui, je ne vais considérer les fuites mémoires que dans le cadre de la synchronisation du cycle de vie des Threads et des activités. Cet article ne traite pas des fuites mémoires dans leur généralité.

0-1. Les Threads

Il faut toujours garder en tête quand on fait de la programmation Android que si une activité réagit en plus de 5 secondes, elle sera tuée par l'ActivityManager qui la considèrera comme morte.

Les IHMs de l'activité sont dans une Thread qui lui est propre (comme en swing). C'est cette Thread qui est chargée de l'interaction avec l'utilisateur. Ainsi pour effectuer un traitement, il faut lancer une autre Thread (dites de background, de traitement ou d'arrière-plan) qui effectue le traitement. Plusieurs façons d'interagir entre les Threads en arrière-plan et la Thread d'IHM sont possibles.

Mais surtout il faut garder toujours en tête qu'aucun traitement ne doit être effectué dans la Thread d'IHM !

Deux objets dédiés à ce pattern sont disponibles nativement sur Android, les Handlers et les AsyncTasks.

1. Les Handlers

Le Handler est associé à l'activité qui le déclare et travaille au sein de la 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, la Thread qui appelle le Handler a la charge du traitement. Le Handler ne doit que mettre à jour l'IHM, tout autre comportement est une erreur de conception.

Une Thread communique avec un Handler au moyen de messages (de l'objet Message pour être exact). Pour cela :

  • La 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 à la Thread (en lui passant d'autres paramètres au moyen d'un Bundle).
  • La 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. Il a à charge de mettre à jour l'IHM en fonction de ces données.
Handler2.JPG


L'exemple suivant met à jour une ProgressBar:

 
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 Android2ee
 * @goals Cette classe a pour but de montrer comment utiliser les Handlers et les Threads
 */
public class HandlerTuto extends Activity {
    /**     * La ProgressBar à mettre à jour     */
    ProgressBar bar;
    /**     * La clef dans le bundle pour incrémenter la progressBar     */
    private final String PROGRESS_BAR_INCREMENT="ProgreesBarIncrementId";
    /**     * Le Handler à charge de la communication entre la Thread de background et celle de l'IHM     */
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int progress=msg.getData().getInt(PROGRESS_BAR_INCREMENT);
            // Incrémenter la ProgressBar, on est bien dans la Thread de l'IHM
            bar.incrementProgressBy(progress);
            // On peut faire toute action qui met à jour l'IHM
            
        }
    };
    /**     * L'AtomicBoolean qui gère la destruction de la Thread de background     */
    AtomicBoolean isRunning = new AtomicBoolean(false);
    /**     * L'AtomicBoolean qui gère la mise en pause de la Thread de background     */
    AtomicBoolean isPausing = new AtomicBoolean(false);

    // Création de l'activité
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        // Définition de la ProgressBar
        bar = (ProgressBar) findViewById(R.id.progress);
        bar.setMax(210);
    }

    /** Méthode du cycle de vie de l'activité (lancement de celle-ci) */
    public void onStart() {
        super.onStart();
        // initialisation de la ProgressBar
        bar.setProgress(0);
        // Définition de la Thread (peut être effectuée dans une classe externe ou interne)
        Thread background = new Thread(new Runnable() {
            /**
             * Le Bundle qui porte les données du Message et sera transmis au Handler
             */
            Bundle messageBundle=new Bundle();
            /**
             * Le message échangé entre la Thread et le Handler
             */
            Message myMessage;
            // Surcharge de la méthode run
            public void run() {
                try {
                    // Si isRunning est à false, la méthode run doit s'arrêter
                    for (int i = 0; i < 20 && isRunning.get(); i++) {
                        // Si l'activité est en pause mais pas morte
                        while (isPausing.get() && (isRunning.get())) {
                            // Faire une pause ou un truc qui soulage le CPU (dépend du traitement)
                            Thread.sleep(2000);
                        }
                        // Effectuer le traitement, pour l'exemple je dors une seconde
                        Thread.sleep(1000);
                        // Envoyer le message au Handler (la méthode handler.obtainMessage est plus efficace
                        // que créer un message à partir de rien, optimisation du pool de message du Handler)
                        //Instanciation du message (la bonne méthode):
                        myMessage=handler.obtainMessage();    
                        //Ajouter des données à transmettre au Handler via le Bundle
                        messageBundle.putInt(PROGRESS_BAR_INCREMENT, 1);
                       //Ajouter le Bundle au message
                        myMessage.setData(messageBundle);
                        //Envoyer le message
                        handler.sendMessage(myMessage);
                    }
                } catch (Throwable t) {
                    // gérer l'exception et arrêter le traitement
                }
            }
        });
        //Initialisation des AtomicBooleans
        isRunning.set(true);
        isPausing.set(false);
        //Lancement de la Thread
        background.start();
    }
    
 /************************************************************************************/
/** Gestion du cycle de vie *******************************************************************/
 /**************************************************************************************/
    //Méthode appelée quand l'activité s'arrête 
    public void onStop() {
        super.onStop();
        //Mise-à-jour du booléen pour détruire la Thread de background
        isRunning.set(false);
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onPause()
     */
    @Override
    protected void onPause() {
        super.onPause();
        // Mise-à-jour du booléen pour mettre en pause la Thread de background
        isPausing.set(true);
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onResume()
     */
    @Override
    protected void onResume() {
        super.onResume();
        // Mise-à-jour du booléen pour relancer la Thread de background
        isPausing.set(false);
    }

}

Cet exemple utilise des objets de type AtomicBoolean, l'explication est donnée dans le paragraphe traitant des fuites mémoires.

1-1. Suis-je dans la Thread de l'IHM ou pas ?

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

2. La désynchronisation avec l'AsyncTask

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 3 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 ).

Une dernière chose d'importance est que la classe AsyncTask (et donc vos classes filles) s'exécute dans deux Threads distinctes ; la Thread d'IHM et la Thread de traitement.


Un exemple (toujours celui qui met à jour une ProgressBar):

 
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 une 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 une Thread à part, les autres méthodes s'exécutent dans la Thread de l'IHM .

onPreExecute est appelée par la 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.

AsyncTask.JPG

Exemple :

 
Sélectionnez
/**
 * @author Android2ee
 * @goals Cette classe montre un usage simple du Pattern AsyncTask. Attention, elle génère des fuites mémoires
 *  si elle est utilisée telle quelle.
 */
public class AsyncTuto extends Activity {
    /**    * La ProgressBar à mettre à jour     */
    ProgressBar bar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // Définition de la ProgressBar
        bar = (ProgressBar) findViewById(R.id.progress);
        bar.setMax(210);
        // Lancement de l'AsynchTask
        new MyAsyncTask().execute();
    }

    /**
     * Cette classe montre une simple dérivation de la classe AsyncTask
     */
    class MyAsyncTask extends AsyncTask<Void, Integer, String> {
        /**     * Un compteur */
        Integer count = 0;

        // Surcharge de la méthode doInBackground (Celle qui s'exécute dans une Thread à part)
        @Override
        protected String doInBackground(Void... unused) {
            try {
                while (count < 20) {
                    //incrémente le compteur
                    count++;
                    // Faire une pause
                    Thread.sleep(1000);
                    //Donne son avancement en appelant onProgressUpdate
                    publishProgress(count);
                }
            } catch (InterruptedException t) {
                // Gérer l'exception et terminer le traitement
                return ("The sleep operation failed");
            }
            return ("return object when task is finished");
        }

        // Surcharge de la méthode onProgressUpdate (s'exécute dans la Thread de l'IHM)
        @Override
        protected void onProgressUpdate(Integer... diff) {
             // Mettre à jour l'IHM
            bar.incrementProgressBy(diff[0]);
        }

        // Surcharge de la méthode onPostExecute (s'exécute dans la Thread de l'IHM)
        @Override
        protected void onPostExecute(String message) {
             // Mettre à jour l'IHM
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
        }
    }
}

3. AsyncTask ou Handler

Ces deux méthodes ont pour but d'effectuer des traitements liés aux IHMs dans des Threads indépendantes de celle de l'IHM. La question est de savoir laquelle choisir dans quelles circonstances.


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 ( par exemple la communication Bluetooth entre deux appareils utilise ce pattern).


Ainsi, si vous avez un traitement qui correspond à effectuer la même action sur un ensemble d'éléments donnés et connus avant le début du traitement, l'utilisation de l'AsyncTask est préconisée. Sinon, il y a de grandes chances qu'il vous faille utiliser le pattern du Handler.


En conclusion: un traitement par lots s'effectuera avec une AsyncTask et un traitement nécessitant une communication dynamique entre la Thread de traitement et l'IHM utilisera le pattern du Handler.

4. Threads et fuites mémoires

La question qui se pose est « Que se passe-t-il lorsque l'activité suit son cycle de vie et est détruite puis recréée ? Typiquement une rotation de l'écran? Que devient la Thread de traitement ? »

Dans la plupart des cas, le développeur ne fait pas attention et l'ancienne Thread n'est pas détruite, une nouvelle Thread est mise en place. Le traitement peut rester cohérent (ou pas).

La même chose se produit avec les AsynchTask bien que seuls les Handlers soient cités dans la suite de l'article. Par contre, les tutoriels disponibles traitent tous les cas.

Le schéma mémoire qui se met en place est alors le suivant :

HandlerMemoryLeak2.JPG

On s'aperçoit que la destruction de l'activité ne détruit pas la Thread, celle-ci reste « en vie ». Pire, elle continue de pointer vers le Handler et l'activité, qui bien que considérés détruits par Android ne le sont pas (vous ne pouvez pas y accéder, ni afficher l'activité.). Le GarbageCollector détecte que ces ressources sont utilisées (en effet la Thread pointe sur ces espaces mémoires) et ne les collecte pas.

Pire encore, quand l'activité est recréée (typiquement un changement d'orientation), elle recrée aussi une nouvelle Thread et la lance.

On se retrouve au final (suite à un changement d'orientation par exemple) avec :

  • deux threads qui effectuent le même traitement mais n'en sont pas au même point,
  • Une Activity et un Handler actifs,
  • Une activité et un Handler fantômes, ni vraiment morts ni vraiment vivants.

Alors quelle est la parade ?

Avant de trouver la solution, il faut tout d'abord se poser les questions suivantes :

  • La Thread doit-elle être détruite lorsque l'activité se termine ?
  • La Thread doit-elle se terminer lorsque l'activité est détruite puis recréée ?
  • L'utilisateur a-t-il son mot à dire ?

Ces questions sont fondamentales pour le Design Pattern que vous allez implémenter pour votre traitement.

Clairement si la fin de l'activité ne termine pas la Thread, il est fort à parier que vous auriez du mettre un service entre l'activité et la Thread. Celui-ci ayant à charge le traitement est lancé par l'activité et continue indépendamment du cycle de vie de l'activité.

Dans les cas où le cycle de vie de votre activité doit être lié à celui de votre Thread, deux cas s'offrent à vous : l'utilisation de deux booléens « synchronized » appelés AtomicBoolean ou l'utilisation en plus de ces deux éléments de la méthode onRetainNonConfigurationInstance.

Deux projets Eclipse démontrant cette fuite mémoire sont disponible ici : page des tutoriels sur les Handlers .

L'un démontre cette fuite avec un Handler, l'autre la démontre avec un AsyncTask.

4-1. Utilisation des AtomicBooleans pour lier le cycle de vie de la Thread à celui de l'activité.

Les AtomicBooleans sont des objets de type Boolean qui sont thread safe. En effet les méthodes d'accès aux valeurs du booléens sont « synchronized ». Ainsi on accède à la valeur de ce type d'objet par appel à la méthode get() et on change sa valeur en utilisant la méthode set.

 
Sélectionnez
public class HandlerTutoActivity extends Activity {
/*****************************************************************************************/
/** Gérer le Handler et la Thread *************************************************/
/*****************************************************************************************/
/** * Le Handler */
private Handler handler;
/** * Le AtomicBoolean pour lancer et stopper la Thread */
private AtomicBoolean isThreadRunnning = new AtomicBoolean();
/** * Le AtomicBoolean pour mettre en pause et relancer la Thread */
private AtomicBoolean isThreadPausing = new AtomicBoolean();
/** * La Thread */
Thread backgroundThread;

/****************************************************************************************/
/** Gérer l'activité ********************************************************************/
/***************************************************************************************/

/** Appelé à la création de l'activité. */
@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
	// Instancier la ProgressBar
	progressBar = (ProgressBar) findViewById(R.id.progressbar);
	progressBar.setMax(100);
	// définition du Handler
	handler = new Handler() {
		/* * (non-Javadoc) * 
		 * @see android.os.Handler#handleMessage(android.os.Message) */
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			Log.d(TAG, "handle message called ");
			// s'assurer que la Thread est bien en mode Run avant de faire quelque chose
			if (isThreadRunnning.get()) {
				Log.w(TAG, "handle message calls updateProgress ");
				updateProgress();
			}
		}
	};
	// Définition de la Thread et liaison avec le Handler
	backgroundThread = new Thread(new Runnable() {
		/**
		 * Le message échangé entre la Thread et le Handler
		 */
		Message myMessage;

		/** (non-Javadoc) * * @see java.lang.Runnable#run()*/
		public void run() {
			try {
			while (isThreadRunnning.get()) {
				if (isThreadPausing.get()) {
					// Faire une pause cohérente avec le traitement, soulager le CPU
					Thread.sleep(2000);
				} else {
					// Faire un traitement 
					Thread.sleep(100);
					// Obtenir le Message
					myMessage = handler.obtainMessage();
					// envoyer le message au Hanlder
					handler.sendMessage(myMessage);
				}
			}
			} catch (Throwable t) {
				// Termine la Thread
			}
		}
	});
	// Initialiser le booléen isThreadRunning
	isThreadRunnning.set(true);
	//Lancer la Thread
	backgroundThread.start();
}

/* * (non-Javadoc) * * @see android.app.Activity#onDestroy() */
protected void onDestroy() {
	// Tuer la Thread
	isThreadRunnning.set(false);
	super.onDestroy();
}

/* * (non-Javadoc) *  * @see android.app.Activity#onPause() */
protected void onPause() {
	//Mettre la Thread en pause
	isThreadPausing.set(true);
	super.onPause();
}

/* * (non-Javadoc) *  * @see android.app.Activity#onResume() */
protected void onResume() {
	// Relancer la Thread
	isThreadPausing.set(false);
	super.onResume();
}

Ce pattern (qui est le même que celui présenté en début d'article) permet d'obtenir le schéma mémoire suivant lors du passage de l'activité par les méthodes onDestroy, onCreate :

HanlderMemoryWithAtomic2.JPG

Ce schéma mémoire a le mérite d'être sans fuite mémoire, a contrario, il réinitialise le traitement de la Thread (en fait il en créé un nouvelle) à chaque redémarrage de l'activité. Il pourrait être utile de sauvegarder l'état d'avancement de la Thread dans la méthode onDestroy puis de restaurer cet état dans la méthode onCreate.

Cette solution ne permet pas de pallier au problème du changement de configuration de l'appareil qui reconstruit l'activité immédiatement après sa destruction. Pour cela il faut utiliser la méthode onRetainNonConfigurationInstance.

Un tutoriel présentant cette solution est disponible ici : page des tutoriels sur les Handlers .

4-2. Utilisation de la méthode onRetainNonConfigurationInstance

Attention : Pour garder un caractère compréhensible, ce paragraphe explique l'utilisation de cette méthode. Mais si vous utilisez le code décrit ci-dessous directement vous ne gérez plus la fuite mémoire générée par la destruction de l'activité. Il faut inclure dans la solution de ce paragraphe, l'utilisation des AtomicBoolean du paragraphe précédent qui permettent de n'avoir jamais de fuite mémoire. Le tutoriel HandlerActivityBindingThreadTuto disponible sur Android2ee vous présente la solution complète et propre, il se télécharge ici : page des tutoriels sur les Handlers .

Mais tout d'abord « Qu'es aquò la méthode OnRetainNonConfigurationInstance ? » comme dirait mon grand-père.

De manière générale les méthodes Object publicgetLastNonConfigurationInstance() et public Object onRetainNonConfigurationInstance() permettent de passer un objet entre deux instances d'une activité lorsque celle-ci est détruite pour être immédiatement recréée. Il faut donc toujours tester la valeur de retour (null ou pas) et être cohérent avec ce retour.

On renvoie l'objet (ou la liste d'objets) avec la méthode onRetainNonConfiguartionInstance et on le récupère avec getLastNonConfigurationInstance.

Nous utiliserons ces méthodes pour passer en paramètre la Thread ; ce qui donne :

 
Sélectionnez
/** Appelée à la première creation de l'activité */ 
@Override 
public void  onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Faire quelque chose 
backgroundThread = (Thread) getLastNonConfigurationInstance();
//Tester si la Thread est nulle ou pas et adapter le traitement en fonction
}
@Override 
public Object onRetainNonConfigurationInstance() {
 //Renvoyer la Thread 
 return backgroundThread;
}

Ce DesignPattern permet d'obtenir le schéma mémoire suivant :

HanlderMemoryWithOnRetain2.JPG

Remarquez que ce schéma mémoire a le bon goût lors de la destruction puis recréation (immédiate) de l'activité de conserver la même Thread de Traitement et d'éviter les fuites mémoires. Il est à noter que sans les AtomicBooleans lorsque l'activité s'arrête, vous générez une fuite mémoire, il faut donc impérativement mixer les deux approches.

Un tutoriel présentant cette solution est disponible ici : page des tutoriels sur les Handlers .

5. Conclusion

Suite à cet article vous êtes censés être capable d'effectuer des traitements dans vos applications qui ne gèlent pas vos IHMs et qui ne génèrent pas de fuite mémoire. J'espère que vous vous en souviendrez dans vos projets ou quand vous expliquerez à vos stagiaires comment coder proprement. En attendant, bonne continuation à vous.

6. 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.

7. Récupération des tutoriels

Cet article est associé à un tutoriel que vous trouverez en libre téléchargement sur le site Android2ee. À l'adresse suivante : Page des tutoriels des Handlers-AsyncTask sur Android2ee

Liste des tutoriels disponibles :

Tutorial
OrphanThreadDemo
HandlerTuto
HandlerActivityBindingThreadDemo
OrphanAsyncTaskThreadTuto
AsyncTaskTuto

8. 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


9. 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

10. 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.

11. Remerciements

J'adresse ici tous mes remerciements à Feanorin pour son implication, son aide et sa sympathie et à Erielle pour l'excellence de ses corrections orthographiques.

Je remercie les correcteurs techniques MrDuChnok, David55 et Feanorin pour la pertinence de leurs remarques.

Je remercie spécialement Monsieur Adam Daniel, DRH de développez.com, pour ses mails nocturnes, ses encouragements et son aide qui m'est précieuse.

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

  

Copyright © 2012 Mathias Seguy. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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.