Handler

Le handler, ou le gestionnaire possède des méthodes qui vont nous permettre de recevoir des instances de la classe Message ou Runnable.

 

Les messages

Il s'agit simplement de gérer des messages dans une file de messages pour un thread, le thread qui a créé l'instance de Handler. Le principe des files de messages sont utilisées sous Windows pour gérer des évènements qui se produisent avec des widgets, Sous X Window, ou encore Les files de messages IPC...

Il s'agit donc de quelque chose de très courant dans le monde informatique. Sous android, nous utiliserons la classe Message.

La file de messages est de type FIFO, donc le premier message posté sera le premier a être lu.

 

Lecture d'un message

Votre instance de handler doit implémenter la méthode suivante:

public void handleMessage(Message msg) {

[...] mon code [...]

}

Cette méthode sera déclenchée à chaque fois qu'il y aura un nouveau message dans la file de messages et tant qu'il y a des messages à traiter.

Image non trouvée !Le traitement d'un message doit rester suffisement rapide, car les autres messages ne seront pas traités tant que celui en cours ne sera pas terminé !

Image non trouvée !Comme on peut le constater, cette méthode attend en paramètre une instance de la classe Message. C'est à partir de cette instance que nous retrouverons les éléments du message. C'est à priori cette instance de Message que nous traiterons dans mon code, mais ce n'est plus le rôle de Handler mais de Message. Donc si vous n'avez toujours pas compris qu'il faut voir la classe Message...

 

Envoyer des messages

Avec un message:

Pour envoyer un message, il faut d'abord se créer le corp du message. Pour cela, nous utiliserons une instance de la classe Message que nous obtiendrons en utilisant la méthode obtain() avec la classe Message ou obtainMessage() avec la classe Handler.

Une fois l'instance créée, pour envoyez ce message au Handler, nous utiliseront une des méthodes suivantes:

- sendMessage(Message msg) place immédiatement le message dans la file.
- sendMessageAtFrontOfQueue(Message msg) place immédiatement le message en tête de file. Ne faire cela que pour des messages prioritaires !
- sendEmptyMessageAtTime(Message msg,long uptimeMillis): placer le message dans la file de messages à l’instant indiqué en paramètre. Cet instant s'exprime en millisecondes par rapport à l’uptime du système (SystemClock.uptimeMillis()).
- sendMessageDelayed(Message msg, long delayMillis) place le message dans la file de messages après un certain délai, exprimé en millisecondes.

Avec un message vide: Il ne sera pas nécessaire dans ce cas de passer par handler.obtain() pour obtenir une instance de message puisque non envoyé !

- sendEmptyMessage(int what): Place un message vide. Seul l'entier what pourra être renseigné dans la file de messages.
- sendMessageAtFrontOfQueue(int what) place immédiatement le message en tête de file. Ne faire cela que pour des messages prioritaires !
- sendEmptyMessageAtTime(int what,long uptimeMillis): placer le message dans la file de messages à l’instant indiqué en paramètre. Cet instant s'exprime en millisecondes par rapport à l’uptime du système (SystemClock.uptimeMillis()).
- sendMessageDelayed(int what, long delayMillis) place le message dans la file de messages après un certain délai, exprimé en millisecondes.

 

Exemple de code avec des messages

Gestion d'un message pour faire avancer une barre de progression:

Tout d'abord le fichier main.xml pour définir la barre de progression dans notre activité

Puis le code du fichier TstHandler pour gérer tout cela...

Image non trouvée !Initialement, dans handleMessage, après traitement des messages, j'utilisais msg.recycle(); pour libérer le message en indiquant que cette option était facultatif, le système faisant très bien le boulot...

Il semble que cela ne soit pas aussi vrai que cela, et pire, que cette commande ne soit pas suffisante, car j'ai déjà obtenu des exception avec :

E/AndroidRuntime(708): android.util.AndroidRuntimeException: { what=valeur when=-1ms arg1=valeur } This message is already in use.

Pour m'en sortir, j'ai du faire removeMessages (msg.what). Je ne sais pas encore pourquoi !

 

Runnable

Il est possible de passer dans la file de messages un objet Runnable. Le handler exécutera cet objet dans l'UI Thread.

Les méthodes post() de Handler, permettent de passer des objets Runnable dans la file d’attente des événements.

post(Runnable r) Ajouter un objet Runnable dans la file de messages
final boolean postAtFrontOfQueue(Runnable r) Ajouter un objet Runnable en premier dans la file des messages (priorité d'exécution car en premier)
final boolean postAtTime(Runnable r, Object token, long uptimeMillis) Ajouter un objet Runnable dans la file des messages en indiquant quand devra être exécuté celui-ci
final boolean postAtTime(Runnable r, long uptimeMillis) Ajouter un objet Runnable dans la file des messages en indiquant quand devra être exécuté celui-ci
final boolean postDelayed(Runnable r, long delayMillis) Ajouter un objet Runnable dans la file des messages en indiquant que celui-ci doit être exécuté après un certain temps.

Exemple avec Runnable

Toujours votre barre de progression qui indique où vous en êtes dans votre traitement.

Le principe est exactement le même que pour les messages:

Le fichier main.XML pour définir notre barre de progression sera même simplement repris de l'exemple précédent !

Puis le code pour gérer tout cela.

La seule différence: Pas de code pour gérer les messages (pas besoin pour cet exemple, puisque le message est remplacé par le lancement d'un objet Runnable)

Passage d'un objet Runnable au Handler.

Image non trouvée !Il sera éventuellement possible d'indiquer dans la méthode run() de Runnable un niveau de priorité Android (mais correspondant aux priorités sous Unix):

Android.os.Process.setThreadPriority(Android.os.Process.THREAD_PRIORITY_BACKGROUND);

Cela aura pour effet de donner un niveau faible de priorité.