6 mai 2014

Android - Introduction aux concepts et aux cycles de vie d'une application


Cet article est une introduction aux concepts d'Android et aux cycles de vie d'une application.

Applications Android

Il existe différentes catégories d'applications Android :
  • Foreground : Avec interface utilisateur
    • ce type d'application dispose d'une interface graphique qui permet d'interagir avec l'utilisateur.
    • L'application est mise en veille lorsque l'utilisateur change d'application.
  • Background : En arrière-plan
    • ces applications tournent en arrière-plan et ne sont quasiment pas visibles par l'utilisateur.
    • Exemple : réveil
  • Intermittent :
    • ce type d'application dispose d'une interface utilisateur mais continue de fonctionner en arrière-plan. 
    • Exemple: lecteur de musique
  • Widgets et Live wallpapers

Contenu d'une application

Une application Android est un ensemble de composants qui peuvent coopérer entre-eux et qui peuvent être utilisés par d'autres applications.

Une application Java traditionnelle a un seul point d'entrée qui est la méthode main, alors qu'une application Android peut avoir des points d'entrée multiples en fonction d'où vient l'utilisateur et de ce qu'il veut faire ensuite.

L'interface utilisateur est gérée via des vues (layout) et des activités (classes Activity).

Les processus en arrière-plan d'une application sont définis via les services (classes Service).

Activité (Activity)

Les activités (classes Activity) gèrent les écrans affichés à l'utilisateur ainsi que les interactions avec l'utilisateur depuis cet écran.

L'activité fait partie de la couche de présentation.

Exemple : Dans une application de messagerie, une activité peut être chargée d'afficher l'écran présentant la liste de message et de traiter les actions de l'utilisateur sur cet écran comme l'action de consultation d'un des messages.

Service

Un service (classe Service) tourne en tâche de fond et n'est pas visible par l'utilisateur.

Il permet d'effectuer des traitements en tâche de fond.

Exemple: un service qui joue de la musique pendant que l'utilisateur navigue sur Internet.

Architecture orientée événements

Android dispose d'un framework de messages inter-applicatif qui permet aux composants de s'envoyer des messages et de réagir aux messages reçus.

Nous avons ainsi une architecture orientée événements (Event-Driven Architecture) : les composants des applications réagissent aux événements des autres applications et des composants natifs au système.

Intention (Intent)

La classe Intent permet de définir un message.

Le message Intent permet par exemple :
  • de passer d'un écran à un autre, c'est à dire d'une activité à une autre. Le message Intent contient la classe de l'activité de l'écran à démarrer et peut contenir des paramètres à fournir à cette nouvelle activité. La première activité se met alors en pause et la nouvelle activité démarre.
  • // code de l'activité 1
    Intent intentActivite2 = new Intent(this,Activite2.class);
    intentActivite2.putExtra("nom_parametre_1", "valeur"); // Paramètre
    startActivity(intentActivite2); // démarre l'activité 2 et met en pause l'activité 1

Récepteur de diffusion (BroadcastReceiver)

Un BroadcastReceiver permet à une application d'être à l'écoute des messages Intent qui sont diffusés par les autres applications.

Si un des messages Intent reçu par le BroadcastReceiver correspond aux critères de l'application, alors le BroadcastReceiver a la possibilité de démarrer cette application.

Exemple: dans la cas de la réception d'un SMS, le BroadcastReceiver peut démarrer l'application qui attend des événements liés à la réception de messages.

Cycle de vie d'une application

Chaque application fonctionne au sein de son propre processus isolé des autres processus des autres applications.

En raison de ressources mémoires et système limitées, Android peut être agressif et tuer les processus qui ne sont plus utilisées ou en pause pour libérer de la mémoire. Ceci permet de conserver une fluidité et une réactivité à l'utilisation. Cependant, il faudra veiller à sauvegrder les données critiques avant que le processus ne soit détruit par le système.

Les priorités des processus déterminent l'ordre où les processus sont détruits par le système.

Priorités et Etats des processus d'une application

L'état des processus d'une application détermine la priorité donnée à cette application. Les processus qui ont les priorités les plus faibles seront tuées en premier par le système.
  • Priorité Critique
    • Processus Actif :
      • l'utilisateur interagit actuellement avec le processus :
        • activités à l'état actif : qui sont en avant-plan et répondent aux actions de l'utilisateur
        • les BroadcastReceiver qui traitent actuellement un message Intent
        • les services en avant-plan
        • les services en cours de démarrage ou d'arrêt
      • Règle : 
        • Les ressources des autres processus de priorités plus faibles peuvent être requises et attribuées à un processus actif
        • Les processus actifs sont tués en dernier, et seulement si aucune ressource système n'est plus disponible
        • Seuls quelques processus peuvent être dans l'état actif
  • Priorité Haute
    • Processus des activités visibles de l'utilisateur 
      • il s'agit des activités dont l'affichage est visible de l'utilisateur, mais qui ne sont pas en avant-plan ou qui sont à moitié masqué par l'affichage d'une autre activité.
    • Processus des services démarrés :
      • Comme les services n'interagissent pas directement avec l'utilisateur, ils ont une priorité plus faible que les activités visibles et les services en avant-plan
  • Priorité Faible :
    • Processus en arrière-plan : il s'agit des activités dont l'affichage n'est plus visible de l'utilisateur et des services arrêtés.
      • Les processus sont tués dans l'ordre chronologique de leur passage en arrière-plan
    • Processus vides : Android conserve une application en mémoire même après que celle-ci ait été arrêté afin d'accélerer son redémarrage lorsque l'utilisateur voudra de nouveau utiliser cette application. 
      • Ce cache peut être libéré par Android dans le cas où les ressources deviennent limitées

Pile d'activités (Activity stack)

Pour qu'un utilisateur passe d'un écran à un autre via l'interface de ces écrans, il faut que les activités de ces différents écrans s'appellent entre elles via des messages Intent. Les activités précédentes sont alors mises en pause.

Cet ensemble d'activités forme une pile d'activités.

Lorsque l'utilisateur appuie sur le bouton Retour ou si l'activité actuelle s'arrête, alors la dernière activité en pause est remise en avant-plan et l'activité actuelle est arrêtée.

Les activités en pause les plus anciennes peuvent être détruites par le système si ce dernier n'a plus de ressources.

Etats d'une activité (Activity states)

Une activité a plusieurs états :
Inactif ⇒ Actif ⇒ En pause/Visible ⇒ Arrêté ⇒ Inactif
  • Actif
    • l'activité est en avant-plan et interagit avec l'utilisateur
    • sa priorité est critique
    • si une autre activité devient active alors celle-ci est mise en pause
    • une fois démarrée, une nouvelle activité a le statut Actif
  • En pause
    • l'activité est en pause dans le cas où son affichage est encore visible de l'utilisateur mais est en partie masquée par l'affichage d'une autre activité
    • si l'affichage d'une activité est entièrement masquée, alors cette activité est arrêtée
  • Arrêté
    • l'activité est arrêtée si elle n'est plus visible de l'utilisateur.
    • l'activité reste en mémoire et contient toutes encore toutes ses informations
    • si les ressources deviennent insufissants, les activités arrêtées les plus anciennes peuvent être terminées et passer à l'état inactif
    • il est important de sauvegarder les données avant que l'activité ne soit détruite par le système
  • Inactif
    • l'activité a été terminée est maintenant inactive
    • elle n'est plus dans la pile des activités
Il faut sauvegarder les données lorsque l'activité est mise en pause ou arrêtée. Ces données doivent être restaurées lorsque l'activité redevient active.

Transitions d'une activité entre ses états

La classe Activity permet l'implémentation des méthodes qui sont appelées lors des transitions entre les états de cette activité :


De Inactif à Actif :
  • Inactif ⇒ Arrêté : l'activité est démarrée pour la première fois
    • onCreate : début du cycle de vie du processus de l'activité
      • recharger l'interface utilisateur
      • lier les données aux champs de saisie
      • démarrer les services et les timers
      • ne pas créer des objets à courte durée de vie
  • Arrêté ⇒ En pause : l'activité était non visible et redevient visible
    • onRestart : (uniquement dans le cas où l'activité était précédemment active puis a été arrêtée)
      • restaurer les informations affichées et saisies avant l'arrêt
      • restaurer les processus de rafraîchissement de l'affichage et des animations
    • puis
    • onStart : préparations des données avant affichage
      • finalisation de l'affichage
      • créer les BroadcastReceiver sans les activer
      • créer les processus de rafraîchissement de l'affichage et des animations
  • En pause ⇒ Actif : l'activité est active et interagit avec l'utilisateur
    • onResume
      • activer les animations et les processus qui rafraîchissent l'affichage (threads, processus)
      • activer les BroadcastReceiver pour recevoir les messages d'événements Intent
      • cette méthode doit être rapide à s'exécuter
De Actif à Inactif :
  • Actif ⇒ En pause : l'activité est mise en pause
    • onSaveInstanceState
      • enregistrement de l'état de l'affichage
    • puis
    • onPause
      • mettre en pause les animations et les processus qui rafraîchissent l'affichage (threads, processus)
      • mettre les BroadcastReceiver en pause
      • cette méthode doit être rapide à s'exécuter
  • En pause ⇒ Arrêté : l'activité n'est plus visible
    • onStop
      • arrêt des animations et des processus de rafraîchissement de l'affichage
      • arrêter les BroadcastReceiver
      • arrêt du GPS, des timers, des services 
      • enregistrement des informations
  • Arrêté ⇒ Inactive : l'activité est définitivement terminée
    • onDestroy : nettoyage de la mémoire et des ressources : threads, processus, connexions à la base de données
      • fin des connexions aux bases de données
      • fin des connexions réseaux
Note: les BroadcastReceiver servent à recevoir les messages Intent afin de réagir aux événements transmis par le système et les autres composants.

L'activité peut être détruite par le système si elle est à l'état "En pause" ou "Arrêté", les méthodes d'arrêt de l'activité "onStop" et "onDestroy" ne sont alors pas obligatoirement appelées s'il ne reste plus assez de mémoire disponible pour le système.