novembre
2011
Bonjour,
Vous avez une activité qui utilise un Handler. Pour cela, vous avez créé votre Handler, redéfini sa méthode handleMessage, vous avez créé et lancer la thread associée au Handler et voilà c’est fini pour la gestion de votre Handler…
La plupart d’entre nous aurons fait un chose pareille et c’est une énorme erreur !!!
Qu’arrive-t-il à votre thread quand votre activité passe en pause, est relancée, est détruite puis re-créée ?
Votre thread devient une thread orpheline !!
Ainsi vous avez écrit quelque chose comme ça :
* The handler
*/
private final Handler slowDownDrawingHandler;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
// handler definition
slowDownDrawingHandler = new Handler() {
/** (non-Javadoc)*/
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
redraw();
}
};
// Launching the Thread to update draw
Thread background = new Thread(new Runnable() {
/**
* The message exchanged between this thread and the handler
*/
Message myMessage;
// Overriden Run method
public void run() {
try {
while (true) {
// Sleep
Thread.sleep(100);
// Do something
myMessage = slowDownDrawingHandler.obtainMessage();
// then send the message
slowDownDrawingHandler.sendMessage(myMessage);
}
}
} catch (Throwable t) {
// just end the background thread
}
}
});
// start the thread
background.start();
En utilisant un code de ce type, quand votre activité meurt ou passé en pause, votre Thread devient orpheline. Plus rien ne peut l’atteindre, la détruire, communiqué avec elle… C’est une grosse erreur (genre tour Eiffel la taille de l’erreur, avec fuite mémoire et tout…).
Quelle est la façon de faire alors? Vous avez à gérer le cycle de vie de votre thread pour qu’elle soit en adéquation avec le cycle de vie de votre activité. Quand votre activité passé en pause, votre thread doit aussi passé en pause, quand elle est relancée votre thread doit l’être aussi, quand votre activité meurt votre thread aussi.
Une façon simple de faire cela est d’utiliser des AtomicBoolean (qui sont des Booleans synchronized) par exemple isPausing et isStopping, de changer leur valeur quand votre activité passe en pause, est relancée ou meurt et d’utiliser ces Booléens pour gérer le cycle de vie de votre thread.
Le code à utiliser est donc le suivant:
private final Handler slowDownDrawingHandler;
/** * An atomic boolean to manage the external thread's destruction */
AtomicBoolean isRunning = new AtomicBoolean(false);
/** * An atomic boolean to manage the external thread's destruction */
AtomicBoolean isPausing = new AtomicBoolean(false);
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
// handler definition
slowDownDrawingHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
redraw();
}
};
// Launching the Thread to update draw
Thread background = new Thread(new Runnable() {
/**
* The message exchanged between this thread and the handler
*/
Message myMessage;
// Overriden Run method
public void run() {
try {
while (isRunning.get()) {
if(isPausing.get()) {
Thread.sleep(2000);
}else {
// Sleep
Thread.sleep(100);
// Do something
myMessage = slowDownDrawingHandler.obtainMessage();
// then send the message
slowDownDrawingHandler.sendMessage(myMessage);
}
}
}
} catch (Throwable t) {
// just end the background thread
}
}
});
// Initialize the threadSafe booleans
isRunning.set(true);
isPausing.set(false);
background.start();
}
/*(non-Javadoc) */
@Override
protected void onPause() {
//and don't forget to stop the thread
isPausing.set(true);
super.onPause();
}
/*(non-Javadoc) */
@Override
protected void onResume() {
//and don't forget to relaunch the thread
isPausing.set(false);
super.onResume();
}
/*(non-Javadoc) */
@Override
protected void onDestroy() {
//and don't forget to kill the thread
isRunning.set(false);
super.onDestroy();
}
Ceci est un exemple de comment résoudre le problème de manière générique. A vous de vous poser la question est de trouver la solution la plus appropriée à la gestion des threads de votre application. Mais n’oubliez pas : une thread orpheline, c’est une erreur qui coûte un bras.
(Pour voir le code en couleur, c’est ici :Version anglaise colorama)
Alors, merci qui?
Merci, Android2ee, les Ebooks de programmation Android :o)
Mathias Séguy
mathias.seguy.it@gmail.com
Auteur Android2EE
Ebooks pour apprendre la programmation sous Android.
Retrouvez moi sur Google+
Suivez moi sur Twitter
Rejoignez mon réseau LinkedIn ou Viadeo
2 Commentaires + Ajouter un commentaire
Référence Android
Mots-clés
Archives
- mars 2015
- février 2015
- janvier 2015
- mai 2014
- mars 2014
- janvier 2014
- décembre 2013
- novembre 2013
- septembre 2013
- mai 2013
- mars 2013
- février 2013
- janvier 2013
- décembre 2012
- novembre 2012
- octobre 2012
- septembre 2012
- août 2012
- mai 2012
- avril 2012
- mars 2012
- janvier 2012
- décembre 2011
- novembre 2011
- septembre 2011
Ce fut un plaisir mon gars ;o)
Merci pour cette précieuse astuce