Android pour les développeurs J2EE

Un modèle asynchrone pour les clients web


précédentsommairesuivant

III. Le modèle AVAT

III-A. Le projet Eclipse

Le projet Eclipse du modèle AVAT est le suivant :

Image non disponible
  • en [1], le projet est un projet Maven ;
  • en [2], les interfaces du modèle ;
  • en [3], leurs implémentations Android.

Le fichier [pom.xml] du projet Maven est le suivant :

 
CacherSélectionnez

Le projet Maven dépend d'Android :

  • ligne 9 : la version d'Android ;
  • lignes 15-20 : la dépendance vers Android ;
  • lignes 21-26 : une dépendance vers des bibliothèques de support d'Android. Ces bibliothèques permettent à des applications conçues pour une certaine version d'Android de s'exécuter sur des versions plus anciennes. Ces bibliothèques de support contiennent les classes manquantes à la version ancienne d'Android.

III-B. Le cœur du modèle

Image non disponible

Revenons à l'architecture AVAT :

Image non disponible
  • l'activité [1] affiche des vues [2] ;
  • la vue [2] lance des actions [3] ;
  • l'action [3] lance des tâches [4] ;
  • une tâche [4] exécute une ou plusieurs méthodes de la couche [métier].

Le modèle AVAT a été conçu pour séparer les différentes tâches (separation of concern) de la couche [Présentation] d'une application Android :

  • l'activité gère l'affichage des vues. Elle n'accède à celles-ci que via un n° et leur interface [IVue] ;
  • la vue sert à saisir des données et à en afficher. Elle vérifie la validité des données saisies. Elle transmet celles-ci à une action identifiée par un n° et son interface [IAction] ;
  • l'action normalement devrait appeler une méthode de la couche [métier] là également via une interface. Cette méthode peut déboucher par l'ouverture d'une connexion réseau dans la couche [DAO]. Avec les versions récentes d'Android, celle-ci doit se faire dans un thread séparé de celui de l'UI (User Interface). Nous appelons ce thread une tâche asynchrone. Dans ce cas, l'action va lancer une ou plusieurs tâches asynchrones identifiées par un n° et leur interface [ITask] ;
  • la tâche asynchrone va exécuter une ou plusieurs méthodes de la couche [métier] via l'interface de celle-ci.

Dans le modèle AVAT, certaines entités font travailler d'autres entités :

  • la vue fait travailler des actions ;
  • l'action fait travailler des tâches.

L'entité qui fait travailler d'autres entités est un patron. Elle implémentera l'interface [IBoss]. L'entité qui travaille est un travailleur. Elle implémentera l'interface [IWorker]. Ainsi,

  • la vue est un patron. Elle implémentera l'interface [IBoss] ;
  • l'action est à la fois un travailleur et un patron car elle fait travailler des tâches. Elle implémentera les interfaces [IBoss] et [IWorker] ;
  • la tâche est un travailleur. Elle implémentera l'interface [IWorker].

Ce modèle est extensible. On peut l'élargir :

Image non disponible

ou le rétrécir :

Image non disponible

Une entité patron a une équipe de travailleurs. Cette équipe implémentera l'interface [ITeam].

Les entités du modèle VAT seront générées par une fabrique d'objets (factory) d'interface [IFactory]. Aucune implémentation n'est proposée car elle est spécifique à chaque application. Nous en ferons une dans tous nos exemples. La fabrique est centrale à l'application. Le concept est tiré de celui d'[ApplicationContext] du framework Spring.

Les vues partagent une même activité Android. Celle-ci peut donc être utilisée pour stocker des informations partagées entre les vues. De façon alternative, nous pouvons utiliser le concept de session du web. Celle-ci implémentera l'interface [ISession]. Dans nos exemples, nous utilisons systématiquement la session pour partager des données entre vues mais c'est une pratique qui peut être discutée. Nous verrons pourquoi.

Passons en revue la définition de ces interfaces :

Interface [IBoss]

Modélise un patron.

Image non disponible
 
CacherSélectionnez
  • lignes 12, 14 : le boss a une identité pour des besoins de traçabilité dans les logs ;
  • ligne 17 : comme toutes les entités du modèle VAT, le boss a accès à la fabrique d'objets ;
  • ligne 20 : le boss a une équipe de travailleurs ;
  • lignes 26, 28, 31 : le boss ou quelqu'un d'autre peut annuler le travail d'un travailleur particulier (lignes 26, 28) ou de toute l'équipe (ligne 31) ;
  • ligne 23 : les travailleurs rendent compte à leur boss du déroulement de leur travail. Les paramètres de la méthode sont :
  • IWorker worker : le travailleur qui rend compte,
  • int eventType : le type d'information que donne le travailleur : WORK_STARTED (le travailleur vient de commencer son travail), WORK_TERMINATED (le travailleur a terminé son travail), WORK_INFO (le travailleur transmet une information à son boss),
  • Object event : une information transmise par le travailleur. Peut être null.
  • ligne 34 : cette méthode est appelée pour signaler au boss que toutes les tâches qu'il a lancées sont terminées ;
  • ligne 37 : le boss lance d'abord toutes les tâches puis par cette méthode signale à son équipe qu'il attend la fin des tâches. Lorsque celle-ci arrivera, la méthode notifyEndOfTasks sera appelée ;
  • ligne 40 : on peut demander au boss de se mettre en mode verbeux. Les événements WORK_STARTED, WORK_INFO et WORK_TERMINATED sont alors logués ainsi que les opérations d'annulation. C'est utile pour déboguer l'application.

Interface [IWorker]

Modélise un travailleur.

Image non disponible
 
CacherSélectionnez
  • ligne 12 : un travailleur a un patron à qui il envoie des notifications via la méthode [IBoss].notifyEvent. Il envoie les notifications WORK_STARTED, WORK_INFO et WORK_TERMINATED.
  • lignes 15-17 : il a une identité. Cela permet de le tracer dans les logs. Cela permet également au patron d'annuler une tâche identifiée par son Id [IBoss].cancel(String workerId) ;
  • ligne 9 : il sait faire un travail. Pour préciser celui-ci, il peut recevoir une suite de paramètres ;
  • ligne 20 : ce travail peut être annulé, généralement par le patron ;
  • ligne 6 : le travailleur a lui aussi accès à la fabrique d'objets.

Interface [ITeam]

Modélise une équipe de travailleurs.

Image non disponible
 
CacherSélectionnez
  • ligne 10 : l'équipe a un patron, un surveillant (monitor). C'est à lui que l'équipe envoie la notification " endOfTasks " lorsque tous les travailleurs ont terminé leurs tâches ;
  • le boss délègue à son équipe de travailleurs certains traitements qu'on lui demande. C'est le cas des méthodes des lignes 13, 16, 18, 21, 24.

Nous présentons maintenant les interfaces des Vues, Actions et Tâches du modèle VAT :

L'interface [Ivue]

Image non disponible

Une vue est un patron car elle gère une équipe d'actions. Elle implémente donc l'interface [IBoss] :

 
CacherSélectionnez

L'interface [Iaction]

Image non disponible

Une action est à la fois :

  • un travailleur : elle travaille pour une vue ;
  • un patron : elle fait travailler des tâches.

Elle implémente donc les interfaces [IBoss] et [IWorker] :

 
CacherSélectionnez

L'interface [Itask]

Image non disponible

Une tâche asynchrone est un travailleur. Elle travaille pour une action.

 
CacherSélectionnez

L'interface [IFactory]

Image non disponible

L'interface [IFactory] permet de demander la référence d'un objet identifié par un nombre :

 
CacherSélectionnez
  • ligne 5, l'objet identifié par id est créé ou recyclé (singleton). Pour sa construction initiale, une suite de paramètres peut être passée.

L'interface [Isession]

Image non disponible

La session permet de stocker des objets, de les retrouver et de les supprimer. Les objets sont identifiés par une chaîne de caractères.

 
CacherSélectionnez

III-C. L'implémentation Android du modèle AVAT

Image non disponible

Le modèle VAT [2, 3, 4] ci-dessus est implémenté par trois classes abstraites [Vue, Action, Task] auxquelles s'ajoute la classe [Team] implémentant l'interface [Iteam].

Image non disponible

Classe [Team]

Elle implémente l'interface [ITeam]. C'est elle qui fait l'essentiel du travail du modèle VAT.

 
CacherSélectionnez
  • ligne 21 : une équipe gère une équipe de travailleurs ;
  • ligne 25 : elle a un patron ou monitor. C'est à ce patron qu'elle signale la fin des tâches ;
  • ligne 23 : elle surveille ou non la fin des tâches. C'est à l'initiative du patron qu'elle commence cette surveillance ;
  • ligne 27 : on peut demander à l'équipe de loguer ce qu'elle fait ;
  • ligne 73 : l'équipe maintient la liste des travailleurs en activité. Lorsqu'elle reçoit la notification WORK_STARTED d'un travailleur, elle ajoute celui-ci dans la liste (ligne 83). Lorsqu'elle recevra la notification WORK_TERMINATED elle l'enlèvera (ligne 87). Dans ce dernier cas, si son boss lui a demandé de surveiller la fin des tâches et qu'il n'y a plus de travailleurs dans l'équipe (tous ont terminé leur tâche), elle appellera la méthode [notifyEndOfTasks] de son boss (ligne 91) ;
  • ligne 98 : l'équipe reçoit une demande de surveillance de la fin des tâches. Elle commence cette surveillance immédiatement (ligne 102). La raison en est la suivante : le boss demandera la surveillance de la fin des tâches après les avoir toutes lancées. Celles-ci vont venir s'accumuler dans l'équipe au moyen des notifications. Entre le moment où le boss lance la dernière tâche et celui où il demande la surveillance de la fin des tâches, celles-ci peuvent être toutes terminées. Si on ne fait pas le test de la ligne 102, on va attendre une notification WORK_TERMINATED qui ne viendra jamais. La demande de surveillance peut-elle intervenir alors qu'une tâche n'a pas encore envoyé sa notification WORK_STARTED ? Auquel cas, trouver une liste de travailleurs vide ne signifierait pas nécessairement la fin des tâches. Il faudra être vigilant sur le moment où la notification WORK_STARTED est envoyée au boss ;
  • ligne 42 : la méthode cancel permet d'annuler une tâche. Le message cancel est transmis à la tâche elle-même. Le travailleur est ensuite retiré de la liste des travailleurs (ligne 46). Si la tâche est aussi un patron, le message cancel va être transmis à tous les membres de son équipe et ainsi de suite. En bout de chaîne, un certain nombre de tâches asynchrones va être annulée.

Voilà pour la classe [Team]. Passons maintenant à la classe [Vue] :

Image non disponible
Image non disponible

La classe abstraite [Vue]

 
CacherSélectionnez
  • ligne 11 : la classe abstraite [Vue] implémente la classe [IVue] déjà décrite. Elle étend la classe Android [Fragment]. Lidée est d'utiliser une activité de type [FragmentActivity] capable d'afficher des fragments ;
  • ligne 14 : l'identité de la vue pour la tracer dans les logs ;
  • ligne 16 : la vue est un [IBoss]. Elle a donc une équipe de travailleurs. Dans le modèle AVAT (Activité-Vues-Actions-Tâches), cette équipe est composée d'actions [IAction]. Dans le modèle AVT (Activité-Vues-Tâches), cette équipe est composée de tâches [ITask]. On notera que ce champ est privé. Les classes filles n'auront donc pas de notion d'équipe. Elles devront passer par leur classe mère pour y avoir accès. Ce choix peut être discuté ;
  • ligne 18 : on est dans Android. On a donc la notion d'activité. Celle-ci sera de type [FragmentActivity]. La vue l'utilisera pour demander un changement de vue ;
  • ligne 21 : la fabrique d'objets de l'application Android. Elle est injectée dans tous les composants VAT ;
  • ligne 24 : la vue en tant que [IBoss] reçoit des notifications de ses travailleurs ;
  • ligne 26 : l'événement est passé à l'équipe. On notera qu'aucun test de nullité n'est fait sur l'équipe. Il faudra donc qu'une vue ait une équipe même vide. L'équipe gère les événements WORK_STARTED et WORK_TERMINATED et génèrera la notification [endOfTasks] pour la vue lorsqu'il n'y aura plus de travailleurs. C'est comme cela que la vue saura que les actions qu'elle a lancées sont terminées. L'événement WORK_INFO n'est pas traité. La classe fille devra redéfinir la méthode pour traiter cet événement ;
    Parce que le champ de la ligne 16 est privé, les classes filles doivent passer par leur classe mère pour gérer l'équipe des travailleurs. On trouve donc un certain nombre de méthodes proposées aux classes filles pour intervenir sur l'équipe : lignes 24, 29, 35, 41, 48, 54, 59.
  • ligne 64 : parce que la vue est un [IBoss], elle doit implémenter la méthode [notifyEndOfTasks]. C'est la méthode appelée par l'équipe lorsque toutes les actions / tâches ont été accomplies. Le travail à faire ici sera défini par la classe fille.

La classe abstraite [Action]

Image non disponible
Image non disponible

La classe abstraite [Action] est la suivante :

 
CacherSélectionnez

La classe [Action] est un [IBoss]. En tant que tel, on trouve des champs et des méthodes déjà rencontrées pour la classe [IVue]. On ne s'y attardera pas. Ce sont

  • les champs des lignes 12, 19, 22 ;
  • les méthodes des lignes 31, 37, 43, 49, 55, 60, 69

On remarquera que là encore, l'équipe ne peut être nulle. Mais elle peut être vide.

Passons en revue les méthodes liées au fait que [Action] est également un [IWorker].

  • ligne 13 : elle a en plus de son identifiant de boss, un identifiant de travailleur. Ils peuvent être ou non identiques ;
  • ligne 16 : en tant que [IWorker], l'action a un boss [IBoss]. Ce boss est une vue ;
  • ligne 25 : l'action peut être annulée par le boss. En tant que [IBoss], elle peut elle-même annuler le travail de son équipe. C'est ce qu'elle fait en ligne 27 ;
  • ligne 66 : en tant que [IWorker], l'action fait un travail. Celui-ci sera défini par la classe fille.

La classe abstraite [Task]

Image non disponible
Image non disponible

La classe [Task] est la tâche asynchrone qui exécute les méthodes de la couche [métier]. Son code est le suivant :

 
CacherSélectionnez
  • ligne 8 : la classe [Task] étend la classe Android [AsyncTask]. Cette classe a une méthode qui s'exécute dans un thread différent de celui de l'UI. La classe [Task] est donc asynchrone.

La classe [Task] est un [IWorker]. On retrouve donc les méthodes rencontrées pour la classe [Action]. Dans le modèle AVAT, on est en bout de chaîne. Lorsque la vue lance une annulation des tâches / actions, cette annulation se propage jusqu'aux tâches asynchrones [Task]. C'est alors la méthode cancel de la ligne 23 qui est exécutée. La tâche asynchrone [AsyncTask] a une méthode cancel qui permet de l'annuler. Son paramètre booléen précise cette annulation. Lorsqu'il est à vrai, l'annulation est faite immédiatement sinon la tâche est autorisée à aller jusqu'au bout de son exécution.

En tant que [IWorker], la [Task] fait un travail. C'est la méthode de la ligne 29 qui assure ce travail. La ligne 31 fait ce travail dans un thread à part de celui de l'UI. La méthode [executeOnExecutor] est une méthode de [AsyncTask]. Pour mieux comprendre la classe [Task], il nous faut parler de sa classe parent [AsynTask<Object, Object, Void>] (ligne 8).

La classe AsynTask<Object, Object, Void>

D'après la documentation Android :

An asynchronous task AsyncTask< Params , Progress , Result > is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params , Progress and Result , and 4 steps, called onPreExecute , doInBackground , onProgressUpdate and onPostExecute .

  • la méthode [doInBackGround] est la méthode exécutée en tâche de fond. Sa signature est la suivante
 
Sélectionnez
1.
protected abstract Result doInBackground (Params... params)

Elle reçoit une suite de paramètres de type Params . Pour nous ce type sera Object . C'est le premier type générique de notre signature AsyncTask< Object ,Object,Void>. Elle rend une donnée de type Result . Nous, nous ne rendrons aucun résultat. C'est le troisième type générique de notre signature AsyncTask<Object,Object, Void > ;

  • la méthode [onProgressUpdate] permet de publier dans le thread de l'UI l'avancement de la tâche. Sa signature est la suivante :
 
Sélectionnez
1.
protected void onProgressUpdate (Progress... values)

Nous n'utiliserons pas cette méthode. Dans la signature AsyncTask<Object, Object ,Void>, le type Progress est le deuxième type générique, ici Object  ;

  • la méthode [onPreExecute] est exécutée dans le thread de l'UI avant l'exécution de la méthode [doInBackGround]. Sa signature est la suivante :

     
    Sélectionnez
    1.
    protected void onPreExecute ()
    
  • C'est dans cette méthode que la [Task] enverra à son boss la notification [WORK_STARTED]. La notification est donc envoyée dans le thread de l'UI ;

  • la méthode [onPostExecute] est exécutée dans le thread de l'UI après l'exécution de la méthode [doInBackGround]. Sa signature est la suivante :
 
Sélectionnez
1.
protected void onPostExecute (Result result)

où le type Result est le troisième type générique de la signature AsynTask<Object, Object, Void >, donc Void ici. C'est dans cette méthode que la [Task] enverra à son boss les notifications [WORK_INFO] et [WORK_TERMINATED]. Ces notifications sont donc envoyées dans le thread de l'UI.

Au final, la classe [Team] qui gère les notifications [WORK_STARTED, WORK_INFO, WORK_TERMINATED] les reçoit dans le thread de l'UI. C'est pourquoi les méthodes de cette classe n'ont pas été synchronisées.

Nous avons décrit le modèle AVAT. C'est un modèle ultraléger d'environ 13 K octets. Voyons maintenant comment nous pouvons l'utiliser.

III-D. Eléments d'implémentation

Reprenons le modèle AVAT :

Image non disponible

Nous donnons maintenant quelques indications sur l'implémentation réelle des classes abstraites que nous avons décrites.

III-D-1. L'activité Android

L'activité Android sera de type [FragmentActivity]. Le code ressemblera à ce qui suit :

 
CacherSélectionnez
  • ligne 4, l'activité est de type [FragmentActivity]. C'est nécessaire puisque nos vues sont de type [Fragment] ;
  • lignes 4 et 15 : c'est l'activité qui instanciera la fabrique d'objets auprès de laquelle s'approvisionnent les éléments VAT du modèle pour obtenir des objets ;
  • ligne 9-11 : nous utiliserons un indicateur d'attente. Nous le nommerons " sablier " bien que ce n'en soit pas un ;
  • ligne 15 : on trouvera dans la factory des éléments de configuration de l'application rassemblés ici dans une classe Config  ;
  • ligne 17 : l'activité demandera à la fabrique les vues [Fragments] qu'elle gère. Contrairement aux objets [Action] et [Task], les objets [Vue] seront des singletons. La fabrique ne les crée qu'en un exemplaire. Celui-ci est créé lors de la première demande. Ensuite lors des demandes suivantes, la fabrique se contente de rendre la référence de l'exemplaire déjà créé ;
  • lignes 18-21 : affichage d'une vue.

Dans les exemples d'illustration qui suivent, l'activité se limitera à ces fonctionnalités. Donc peu de choses.

III-D-2. La vue

Image non disponible

Une vue pourrait ressembler à ce qui suit :

 
CacherSélectionnez
  • ligne 1 : la vue étend la classe [Vue] du modèle AVAT ;
  • lignes 4, 5 : on suppose que la vue a deux boutons : [Exécuter] pour lancer une ou plusieurs actions, [Annuler] pour les annuler ;
  • ligne 24 : un clic sur le bouton [Exécuter] provoque l'exécution de la méthode ligne 43 ;
  • lignes 46-47 : test de la validité des données saisies ;
  • ligne 50 : la vue instancie la ou les actions qu'elle va lancer. Elle demande à la fabrique la référence des actions. Elle donne deux informations :
  • this  : pour indiquer que la vue est leur patron,
  • Action_01  " : leur identifiant de travailleur ;
  • ligne 52 : la vue indique à sa classe parent [Vue] que l'action passe à l'état démarré ;
  • ligne 54 : elle active les éléments de l'UI qui montrent à l'utilisateur qu'une opération potentiellement longue a commencé. Le bouton [Exécuter] peut par exemple être remplacé par le bouton [Annuler] ;
  • ligne 56 : elle lance l'action. Celle-ci est normalement asynchrone. La vue récupère donc la main. A partir de ce moment, l'utilisateur peut cliquer sur le bouton [Annuler] ;
  • ligne 58 : la vue demande à son parent [Vue] de surveiller la fin des actions lancées. Celui-ci le fera en appelant la méthode [notifyEndOfTasks] de la ligne 67 ;
  • ligne 75 : la vue reçoit des notifications des actions lancées. Elle ne gère pas les notifications [WORK_TERMINATED]. Elle les passe directement à sa classe parent ;
  • ligne 79 : les notifications WORK_INFO lui sont destinées. Elle les gère ;
  • ligne 67 : lorsque toutes les actions lancées auront envoyé la notification [WORK_TERMINATED], le parent [Vue] appellera la méthode [notifyEndOfTasks] de sa classe fille. Celle-ci modifiera l'UI pour indiquer que l'attente est terminée et utilisera les informations qu'elle a reçues pour soit changer l'UI soit passer à une autre vue. Les informations reçues pourront être mises dans une session ;
  • ligne 32 : méthode exécutée lorsque l'utilisateur clique sur le bouton [Annuler] ;
  • ligne 34 : la vue annule toutes les actions lancées ;
  • ligne 36 : elle modifie l'UI pour indiquer que l'attente est terminée ;
  • ligne 38 : elle fait autre chose.

Au final, cette vue est peu différente d'une vue classique Android. Les méthodes propres au modèle AVAT sont les méthodes notifyEvent (ligne 75) qui permet à la vue de récupérer les informations envoyées par les actions et notifyEndOfTasks (ligne 67) qui permet à la vue de savoir que ce qu'elle a demandé a été exécuté.

III-D-3. L'action

Image non disponible

Une action pourrait ressembler à ce qui suit :

 
CacherSélectionnez
  • ligne 13 : l'action étend la classe [Action] du modèle AVAT ;
  • l'action travailleur doit implémenter la méthode [doWork] de la ligne 19 ;
  • l'action patron doit elle implémenter les méthodes [notifyEvent] (ligne 47) et [notifyEndOfTasks] (ligne 38) ;
  • ligne 19 : l'action a reçu des paramètres de la vue pour s'exécuter. Pour faire le travail demandé elle peut avoir besoin de 0 à N tâches asynchrones. Si 0, l'action demandée n'est pas asynchrone. L'action fait alors le travail elle-même et lorsqu'elle a fini, elle envoie les notifications WORK_INFO et WORK_TERMINATED à son boss (la vue) ;
  • si elle a en besoin, l'action va demander à la fabrique des références de tâches (ligne 22). L'action passe deux paramètres à la tâche créée :
  • le boss de la tâche (this),
  • un identifiant ;
  • lignes 23-31 : elle va lancer l'exécution de la tâche asychrone. Celle-ci va s'exécuter dans un thread pris dans un pool de threads. Celui-ci peut être épuisé et alors l'exécution va être refusée avec l'exception de la ligne 26 ;
  • ligne 28 : malgré l'exception, la tâche a pu passer dans l'état [WORK_STARTED], c'est même probable. Nous allons voir en effet que la tâche envoie cette notification dans sa méthode [onPreExecute]. Je n'en ai pas eu confirmation dans la documentation mais tout laisse croire que la ligne 25 se poursuit par l'exécution de cette méthode dans le thread de l'UI. Donc la tâche est probablement dans l'état [WORK_STARTED]. On la passe alors dans l'état [WORK_TERMINATED]. Si elle n'était pas dans l'état [WORK_STARTED], c'est une opération nulle qui ne provoque pas de plantage. Il est important que chaque notification [WORK_STARTED] soit équilibrée par une notification [WORK_TERMINATED] sinon la liste des travailleurs ne sera jamais vide et le boss ne recevra jamais la notification [endOfTasks] ;
  • ligne 30 : on passe l'exception au boss : les informations remontées par les tâches asynchrones peuvent être également des exceptions. Il est important de signaler à la vue qu'une action n'a pu être exécutée.
  • ligne 26 : dans les tests, je n'ai vu apparaître que cette exception. Si d'autres exceptions devaient apparaître, on devrait les gérer également ;
  • ligne 34 : une fois toutes les tâches lancées, l'action va se mettre en attente de leur fin ;
  • ligne 47 : elle va voir passer les notifications [WORK_STARTED, WORK_INFO, WORK_TERMINATED] des tâches lancées. Elle ne gère elle-même que la seconde et passe les autres à sa classe parent ;
  • ligne 38 : l'action reçoit le signal que toutes les tâches sont terminées. Elle va faire ce qu'elle a à faire, peut-être envoyer une notification [WORK_INFO] à son boss puis dans tous les cas, la notification [WORK_TERMINATED].

III-D-4. La tâche asynchrone

Image non disponible

Une tâche asynchrone pourrait ressembler à ce qui suit :

 
CacherSélectionnez
  • ligne 7 : la tâche étend la classe [Task] du modèle AVAT. Celle-ci étend la classe Android [AsynTask<Object, Object, Void>]. On redéfinit trois méthodes de cette classe, [onPreExecute] ligne 13, [doInBackground] ligne 19, [onPostExecute] ligne 33 ;
  • ligne 10 : l'information rendue par la tâche ;
  • ligne 13 : la méthode exécutée dans le thread de l'UI avant la méthode [doInBackground] de la ligne 19. On l'utilise pour envoyer la notification [WORK_STARTED] au boss (l'action) ;
  • ligne 19 : le cœur de la tâche asynchrone. Avec les paramètres que lui a passés l'action, elle exécute une ou plusieurs méthodes de la couche [métier]. Cette exécution est faite dans un thread différent de celui de l'UI. On récupère une information utile (ligne 25) ou une exception (ligne 27), qu'on mémorise dans l'objet de la ligne 10 ;
  • ligne 33 : la méthode exécutée dans le thread de l'UI lorsque [doInBackground] est terminée. La tâche envoie à son patron (l'action) l'info qu'elle a mémorisée en ligne 10 ainsi que la notification [WORK_TERMINATED].

Nous avons dit que le modèle AVAT pouvait être rétréci en un modèle AVT :

Image non disponible

Nous sommes toujours dans un modèle patron / travailleurs :

  • une vue [Vue] est un patron [IBoss]. Son équipe de travailleurs est une équipe de [Task] ;
  • la tâche est un travailleur [IWorker]. Son patron est une vue [Vue].

La partie [IBoss] de l'action disparue va être déportée sur la vue et sa partie [IWorker] sur la tâche. Nous utiliserons ce modèle allégé sur le dernier exemple de ce document.

L'essentiel a été dit. Nous pouvons passer aux exemples d'utilisation du modèle.

Notes  :

  • pour ne pas obscurcir l'objectif de ce document qui est de découvrir le modèle AVAT, nous ne détaillerons pas la construction des vues à l'aide de fichiers XML. Nous donnerons simplement le type et le nom des composants présents sur la vue ;
  • les applications ont été construites pour des tablettes . Aucun effort n'a été fait pour que les vues s'affichent élégamment également sur des smartphones. Dans un cas réel, on aurait bien évidemment fait cet effort.

précédentsommairesuivant

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

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2013 Serge Tahé. 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.