Étapes du cycle de vie d'une activité

1. Bienvenue

Introduction

Dans cet atelier de programmation, vous découvrirez un aspect essentiel d'Android : l'activité. Le cycle de vie d'une activité correspond à l'ensemble des états dans lesquels une activité peut se trouver au cours de sa durée de vie. Il s'étend du moment où l'activité est initialement créée au moment où elle est éliminée et où le système récupère les ressources associées. Lorsqu'un utilisateur passe d'une activité à une autre dans l'application (et lorsqu'il passe de votre application à une autre), l'état évolue en conséquence dans le cycle de vie des activités correspondantes.

En tant que développeur Android, vous devez comprendre le cycle de vie d'une activité. Si les activités ne répondent pas correctement aux changements d'état de cycle de vie, l'application peut générer des bugs étranges, perturber l'expérience utilisateur ou consommer une quantité excessive de ressources système Android. Pour respecter les bonnes pratiques Android, il est essentiel de comprendre le cycle de vie Android et de répondre en conséquence à chacun de ses changements d'état.

Ce que vous devez déjà savoir

  • Qu'est-ce qu'une activité et comment en créer une dans votre application ?
  • Qu'effectue la méthode onCreate() de l'activité et quels types d'opérations sont exécutés dans cette méthode ?

Points abordés

  • Impression des informations de journalisation dans l'outil Logcat
  • Principes de base du cycle de vie de l'objet Activity et rappels appelés lorsque l'activité passe d'un état à un autre
  • Remplacement des méthodes de rappel de cycle de vie pour effectuer des opérations à différents moments du cycle de vie de l'activité

Objectifs de l'atelier

  • Modifier une application de démarrage appelée DessertClicker afin d'ajouter les informations de journalisation affichées dans l'outil Logcat
  • Remplacer les méthodes de rappel de cycle de vie et consigner les modifications apportées à l'état d'une activité
  • Exécuter l'application et observer les informations de journalisation qui s'affichent lorsque l'activité démarre, s'arrête et reprend
  • Implémenter la méthode onSaveInstanceState() pour conserver les données de l'application qui pourraient être perdues en cas de changement de la configuration Ajouter un code pour restaurer ces données lorsque l'application redémarrera

2. Présentation de l'application

Dans cet atelier de programmation, vous utiliserez une application de démarrage appelée DessertClicker. Dans cette application, chaque fois que l'utilisateur appuie sur un dessert à l'écran, il "achète" le dessert. L'application met à jour dans la mise en page les valeurs correspondant au nombre de desserts achetés et au montant total dépensé par l'utilisateur.

8216c20f5571fc04.png

Cette application contient plusieurs bugs liés au cycle de vie Android : par exemple, dans certaines circonstances, les valeurs des desserts peuvent être réinitialisées et revenir ainsi à 0. Comprendre le cycle de vie Android vous aidera à comprendre pourquoi ces problèmes surviennent et comment les résoudre.

Télécharger l'application de démarrage

Téléchargez le code de démarrage de DessertClicker et ouvrez-le dans Android Studio.

Si vous utilisez le code de démarrage de GitHub, notez que le nom du dossier est android-basics-kotlin-dessert-clicker-app-starter. Sélectionnez ce dossier lorsque vous ouvrirez le projet dans Android Studio.

Pour obtenir le code de cet atelier de programmation et l'ouvrir dans Android Studio, procédez comme suit :

Obtenir le code

  1. Cliquez sur l'URL indiquée. La page GitHub du projet s'ouvre dans un navigateur.
  2. Sur la page GitHub du projet, cliquez sur le bouton Code pour afficher une boîte de dialogue.

5b0a76c50478a73f.png

  1. Dans la boîte de dialogue, cliquez sur le bouton Download ZIP (Télécharger le fichier ZIP) pour enregistrer le projet sur votre ordinateur. Attendez la fin du téléchargement.
  2. Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
  3. Double-cliquez sur le fichier ZIP pour le décompresser. Un dossier contenant les fichiers du projet est alors créé.

Ouvrir le projet dans Android Studio

  1. Lancez Android Studio.
  2. Dans la fenêtre Welcome to Android Studio (Bienvenue dans Android Studio), cliquez sur Open an existing Android Studio project (Ouvrir un projet Android Studio existant).

36cc44fcf0f89a1d.png

Remarque : Si Android Studio est déjà ouvert, sélectionnez l'option de menu File > New > Import Project (Fichier > Nouveau > Importer un projet).

21f3eec988dcfbe9.png

  1. Dans la boîte de dialogue Import Project (Importer un projet), accédez à l'emplacement du dossier du projet décompressé. Il se trouve probablement dans le dossier Téléchargements.
  2. Double-cliquez sur le dossier de ce projet.
  3. Attendez qu'Android Studio ouvre le projet.
  4. Cliquez sur le bouton Run (Exécuter) 11c34fc5e516fb1c.png pour créer et exécuter l'application. Assurez-vous qu'elle fonctionne correctement.
  5. Parcourez les fichiers du projet dans la fenêtre de l'outil Projet pour voir comment l'application est configurée.

3. Explorer les méthodes du cycle de vie et ajouter une journalisation de base

Chaque activité correspond à ce que l'on appelle un cycle de vie. Il s'agit d'une analogie au cycle de vie des plantes et des animaux, comme le cycle de vie de ce papillon : les différents états du papillon montrent sa croissance, de la naissance à la mort, en passant par l'âge adulte.

c685f48ff799f0c9.png

Dans la même lignée, le cycle de vie d'une activité est constitué des différents états qu'une activité peut traverser, de sa date d'initialisation à son élimination finale et à la récupération de son espace mémoire par le système. Lorsque l'utilisateur lance votre application, navigue entre les activités, passe de votre application à une autre, l'état de l'activité change. Le schéma ci-dessous illustre tous les états du cycle de vie d'une activité. Comme leur nom l'indique, ces états représentent le statut de l'activité.

c803811f4cb4034b.png

Il est fréquent de vouloir modifier un certain comportement ou exécuter un code spécifique lorsque l'état du cycle de vie de l'activité change. Par conséquent, la classe Activity proprement dite, ainsi que les sous-classes d'Activity comme AppCompatActivity, implémentent un ensemble de méthodes de rappel de cycle de vie. Android appelle ces rappels lorsque l'activité passe d'un état à un autre. Vous pouvez remplacer ces méthodes dans vos propres activités afin d'effectuer des tâches en réponse à ces changements d'état du cycle de vie. Le diagramme suivant illustre les états du cycle de vie et les rappels disponibles qui peuvent être remplacés.

f6b25a71cec4e401.png

Il est important de savoir quand ces rappels seront appelés et que faire dans chaque méthode de rappel. Ces deux schémas sont complexes et peuvent prêter à confusion. Dans cet atelier, au lieu de simplement lire la signification de chaque état et rappel, vous ferez vos propres recherches pour mieux comprendre ces concepts.

Étape 1 : Examiner la méthode onCreate() et ajouter une journalisation

Pour bien comprendre le cycle de vie Android, il est utile de savoir quand les différentes méthodes de cycle de vie sont appelées. Vous pourrez ainsi identifier plus facilement les problèmes potentiels dans DessertClicker.

Pour cela, il vous suffit d'utiliser la fonctionnalité de journalisation Android. La journalisation vous permet d'écrire de courts messages dans une console pendant l'exécution de l'application. Elle vous permet d'indiquer à quel moment différents rappels sont déclenchés.

  1. Exécutez l'application DessertClicker et appuyez plusieurs fois sur la photo du dessert. Notez que la valeur de la colonne Desserts Sold (Desserts vendus) et le montant total en dollars changent.
  2. Ouvrez MainActivity.kt et examinez la méthode onCreate() pour cette activité :
override fun onCreate(savedInstanceState: Bundle?) {
...
}

Dans le schéma du cycle de vie de l'activité, vous avez peut-être reconnu la méthode onCreate(), car vous avez déjà utilisé ce rappel. C'est la seule méthode que chaque activité doit mettre en œuvre. La méthode onCreate() vous permet d'effectuer des initialisations ponctuelles pour votre activité. Par exemple, dans onCreate(), vous gonflez la mise en page, définissez des écouteurs de clics ou configurez une liaison de vue.

9be2255ff49e0af8.png

La méthode de cycle de vie onCreate() est appelée une fois, juste après l'initialisation de l'activité (lorsque l'objet Activity est créé en mémoire). Une fois que onCreate() a été exécuté, l'activité est considérée comme créée.

  1. Dans la méthode onCreate(), juste après l'appel de super.onCreate(), ajoutez la ligne suivante :
Log.d("MainActivity", "onCreate Called")
  1. Importez la classe Log si nécessaire (appuyez sur Alt+Enter ou Option+Enter sur Mac, puis sélectionnez Import [Importer]). Si vous avez activé l'importation automatique, l'opération devrait avoir lieu automatiquement.
import android.util.Log

La classe Log écrit les messages dans l'outil Logcat. Logcat est la console de journalisation des messages. C'est là que les messages Android concernant votre application s'affichent, y compris ceux que vous envoyez explicitement au journal avec la méthode Log.d() ou d'autres méthodes de classe Log.

Cette commande se compose de trois parties :

  • La priorité du message de journal, c'est-à-dire son importance. Dans ce cas, la méthode Log.d() écrit un message de débogage. Les autres méthodes de la classe Log incluent Log.i() pour les messages d'information, Log.e() pour les erreurs, Log.w() pour les avertissements ou Log.v() pour les messages détaillés.
  • La balise de journal (premier paramètre), dans ce cas "MainActivity". La balise est une chaîne qui vous permet de trouver plus facilement vos messages de journal dans Logcat. Elle correspond généralement au nom de la classe.
  • Le message réel (deuxième paramètre) est une chaîne courte qui, dans ce cas, est "onCreate called".

Une constante compile-time est une valeur qui ne change pas. Utilisez const avant une déclaration de variable pour la marquer comme constante au moment de la compilation.

  1. Compilez et exécutez l'application DessertClicker. Vous ne noterez aucune différence de comportement dans l'application lorsque vous appuyez sur le dessert. Dans Android Studio, cliquez sur l'onglet Logcat en bas de l'écran.

6463f587ac6997fe.png

  1. Dans la fenêtre Logcat, saisissez D/MainActivity dans le champ de recherche.

bb0b78600cd47789.png

Logcat peut contenir de nombreux messages, dont la plupart ne vous sont pas utiles. Vous pouvez filtrer les entrées Logcat de différentes manières, mais la recherche est la méthode la plus simple. Étant donné que vous avez utilisé MainActivity comme balise de journal dans le code, vous pouvez l'utiliser pour filtrer le journal. L'ajout de D/ au début signifie qu'il s'agit d'un message de débogage, créé par Log.d().

Votre message de journal comprend la date et l'heure, le nom du package (com.example.android.dessertclicker), la balise de journal (avec D/ au début) et le message réel. Comme ce message apparaît dans le journal, vous savez que onCreate() a été exécuté.

Étape 2 : Implémenter la méthode onStart()

La méthode de cycle de vie onStart() est appelée juste après onCreate(). Après onStart(), l'activité est visible à l'écran. Contrairement à onCreate(), qui n'est appelé qu'une seule fois pour initialiser l'activité, onStart() peut être appelé plusieurs fois au cours du cycle de vie de l'activité.

385df4ce82ae2de9.png

Notez que l'élément onStart() est associé à une méthode de cycle de vie onStop() correspondante. Si l'utilisateur lance votre application, puis revient à l'écran d'accueil de l'appareil, l'activité est interrompue et n'est plus visible à l'écran.

  1. Dans Android Studio, lorsque MainActivity.kt est ouvert et que le curseur se trouve dans la classe MainActivity, sélectionnez Code > Override Methods (Ignorer les méthodes) ou appuyez sur Control+o (Command+o sur Mac). Une boîte de dialogue s'affiche avec une longue liste de toutes les méthodes que vous pouvez remplacer dans cette classe.

e1f2460242b2ae.png

  1. Commencez à saisir onStart pour rechercher la méthode appropriée. Pour accéder à l'élément correspondant suivant, utilisez la flèche vers le bas. Sélectionnez onStart() dans la liste, puis cliquez sur OK pour insérer le code de remplacement récurrent. Le code se présente comme suit :
override fun onStart() {
   super.onStart()
}
  1. Ajoutez la constante suivante au niveau supérieur de MainActivity.kt, au-dessus de la déclaration de classe, class MainActivity..
const val TAG = "MainActivity"
  1. Dans la méthode onStart(), ajoutez un message de journal :
override fun onStart() {
   super.onStart()
   Log.d(TAG, "onStart Called")
}
  1. Compilez et exécutez l'application DessertClicker, puis ouvrez le volet Logcat. Saisissez D/MainActivity dans le champ de recherche pour filtrer le journal. Notez que les méthodes onCreate() et onStart() ont été appelées l'une après l'autre, et que votre activité est visible à l'écran.
  2. Appuyez sur le bouton Accueil de l'appareil, puis utilisez l'écran "Recents" (Actions récentes) pour revenir à l'activité. Notez que l'activité reprend là où elle s'était arrêtée, avec les mêmes valeurs, et que l'élément onStart() est une deuxième fois consignée dans Logcat. Notez également que la méthode onCreate() n'est généralement pas rappelée.
16:19:59.125 31107-31107/com.example.android.dessertclicker D/MainActivity: onCreate Called
16:19:59.372 31107-31107/com.example.android.dessertclicker D/MainActivity: onStart Called
16:20:11.319 31107-31107/com.example.android.dessertclicker D/MainActivity: onStart Called

Étape 3 : Ajouter d'autres instructions de journalisation

Au cours de cette étape, vous implémenterez la journalisation pour toutes les autres méthodes de cycle de vie.

  1. Remplacez les autres méthodes du cycle de vie dans MainActivity et ajoutez des instructions de journalisation pour chacune d'elles. Voici le code :
override fun onResume() {
   super.onResume()
   Log.d(TAG, "onResume Called")
}

override fun onPause() {
   super.onPause()
   Log.d(TAG, "onPause Called")
}

override fun onStop() {
   super.onStop()
   Log.d(TAG, "onStop Called")
}

override fun onDestroy() {
   super.onDestroy()
   Log.d(TAG, "onDestroy Called")
}

override fun onRestart() {
   super.onRestart()
   Log.d(TAG, "onRestart Called")
}
  1. Compilez et exécutez à nouveau DessertClicker, puis examinez Logcat. Cette fois, vous remarquerez qu'en plus des éléments onCreate() et onStart(), il existe un message de journal pour le rappel du cycle de vie onResume().
2020-10-16 10:27:33.244 22064-22064/com.example.android.dessertclicker D/MainActivity: onCreate Called
2020-10-16 10:27:33.453 22064-22064/com.example.android.dessertclicker D/MainActivity: onStart Called
2020-10-16 10:27:33.454 22064-22064/com.example.android.dessertclicker D/MainActivity: onResume Called

Lorsqu'une activité commence de zéro, les trois rappels de cycle de vie suivants sont appelés dans l'ordre :

  • onCreate() pour créer l'application
  • onStart() pour la démarrer et l'afficher à l'écran
  • onResume() pour cibler l'activité et permettre à l'utilisateur d'interagir avec elle

Malgré son nom, la méthode onResume() est appelée au démarrage, même s'il n'y a rien à reprendre.

160054d59f67519.png

4. Explorer quelques cas d'utilisation du cycle de vie

Maintenant que l'application DessertClicker est configurée pour la journalisation, vous pouvez l'utiliser de différentes manières et explorer la façon dont les rappels de cycle de vie sont déclenchés en fonction des utilisations.

Cas d'utilisation 1 : Ouvrir et fermer l'activité

Commencez par le cas d'utilisation le plus basique, qui consiste à démarrer l'application pour la première fois, puis à l'arrêter complètement.

  1. Compilez et exécutez l'application DessertClicker, si elle n'est pas déjà en cours d'exécution. Comme vous l'avez vu, les rappels onCreate(), onStart() et onResume() sont appelés lorsque l'activité démarre pour la première fois.
2020-10-16 10:27:33.244 22064-22064/com.example.android.dessertclicker D/MainActivity: onCreate Called
2020-10-16 10:27:33.453 22064-22064/com.example.android.dessertclicker D/MainActivity: onStart Called
2020-10-16 10:27:33.454 22064-22064/com.example.android.dessertclicker D/MainActivity: onResume Called
  1. Appuyez plusieurs fois sur le cupcake.
  2. Appuyez sur le bouton Retour de l'appareil. Notez que dans Logcat, onPause(), onStop() et onDestroy() sont appelés, dans cet ordre.
2020-10-16 10:31:53.850 22064-22064/com.example.android.dessertclicker D/MainActivity: onPause Called
2020-10-16 10:31:54.620 22064-22064/com.example.android.dessertclicker D/MainActivity: onStop Called
2020-10-16 10:31:54.622 22064-22064/com.example.android.dessertclicker D/MainActivity: onDestroy Called

Dans ce cas, l'utilisation du bouton Retour entraîne la fermeture complète de l'activité (et de l'application). L'exécution de la méthode onDestroy() signifie que l'activité a été complètement arrêtée et que la récupération de mémoire peut avoir lieu. La récupération de mémoire désigne le nettoyage automatique des objets que vous n'utilisez plus. Une fois que l'élément onDestroy() est appelé, le système comprend que ces ressources peuvent être supprimées et commence à nettoyer cette mémoire. 2dcc4d9c6478a9f4.png

L'activité peut également être complètement arrêtée si le code appelle manuellement la méthode finish() ou si l'utilisateur force l'arrêt de l'application. Par exemple, l'utilisateur peut forcer l'arrêt de l'application ou la fermer depuis l'écran des actions récentes. Le système Android peut également arrêter lui-même votre activité si votre application ne s'affiche plus à l'écran depuis longtemps. Cette approche permet d'économiser la batterie et d'allouer l'utilisation des ressources de votre application à d'autres applications.

  1. Revenez à l'application DessertClicker en recherchant toutes les applications ouvertes sur l'écran "Overview" (Aperçu). Notez qu'il peut également s'agir de l'écran "Recents" (Actions récentes) ou "Recent Apps"(Applications récentes). Voici la commande Logcat :
2020-10-16 10:31:54.622 22064-22064/com.example.android.dessertclicker D/MainActivity: onDestroy Called
2020-10-16 10:38:00.733 22064-22064/com.example.android.dessertclicker D/MainActivity: onCreate Called
2020-10-16 10:38:00.787 22064-22064/com.example.android.dessertclicker D/MainActivity: onStart Called
2020-10-16 10:38:00.788 22064-22064/com.example.android.dessertclicker D/MainActivity: onResume Called

L'activité a été éliminée à l'étape précédente. Par conséquent, lorsque vous revenez à l'application, Android lance une nouvelle activité et appelle les méthodes onCreate(), onStart() et onResume(). Notez qu'aucun journal DessertClicker de l'activité précédente n'a été conservé.

La méthode onCreate() est une étape importante. Elle implique la toute première initialisation, où vous configurez la mise en page pour la première fois en la gonflant, et où vous initialisez les variables.

Cas d'utilisation 2 : Quitter l'activité et y revenir

Maintenant que vous avez lancé et fermé complètement l'application, vous avez vu la plupart des états du cycle de vie lorsque l'activité est créée pour la première fois. Vous avez également vu tous les états du cycle de vie d'une activité lorsqu'elle est complètement arrêtée, puis éliminée. Toutefois, lorsque les utilisateurs interagissent avec leur appareil Android, ils passent d'une application à l'autre, retournent à l'écran d'accueil, lancent de nouvelles applications et doivent gérer les interruptions liées à d'autres activités, comme les appels téléphoniques.

Votre activité ne se ferme pas complètement chaque fois que l'utilisateur la quitte :

  • Lorsque votre activité n'est plus visible à l'écran, on parle d'activité en arrière-plan. À l'inverse, on parle d'activité qui se trouve au premier plan ou à l'écran.
  • Lorsque l'utilisateur revient dans votre application, la même activité est redémarrée et redevient visible. Cette partie est appelée cycle de vie visible de l'application.

Lorsque l'application est exécutée en arrière-plan, elle ne devrait généralement pas être exécutée activement pour préserver les ressources système et l'autonomie de la batterie. Le cycle de vie et les rappels de l'élément Activity vous permettent de savoir quand l'application passe en arrière-plan afin de pouvoir suspendre les opérations en cours. Vous relancez ensuite les opérations lorsque l'application est exécutée au premier plan.

Au cours de cette étape, vous allez examiner le cycle de vie de l'activité lorsque l'application passe en arrière-plan, puis revient au premier plan.

  1. Après avoir exécuté l'application DessertClicker, cliquez plusieurs fois sur le cupcake.
  2. Appuyez sur le bouton Accueil de votre appareil et observez l'outil Logcat dans Android Studio. Si vous revenez à l'écran d'accueil, votre application s'exécute en arrière-plan au lieu de s'arrêter complètement. Notez que les méthodes onPause() et onStop() sont appelées, mais pas onDestroy().
2020-10-16 10:41:05.383 22064-22064/com.example.android.dessertclicker D/MainActivity: onPause Called
2020-10-16 10:41:05.966 22064-22064/com.example.android.dessertclicker D/MainActivity: onStop Called

Lorsque l'élément onPause() est appelé, l'application n'est plus active. Après onStop(), elle n'est plus visible à l'écran. Bien que l'activité ait été arrêtée, l'objet Activity est toujours en mémoire, en arrière-plan. L'activité n'a pas été éliminée. L'utilisateur peut revenir dans l'application. Android conserve donc vos ressources d'activité. b488b32801220b79.png

  1. Utilisez l'écran des actions récentes pour revenir à l'application. Notez que dans Logcat, l'activité est redémarrée avec onRestart() et onStart(), puis réactivée avec onResume().
2020-10-16 10:42:18.144 22064-22064/com.example.android.dessertclicker D/MainActivity: onRestart Called
2020-10-16 10:42:18.158 22064-22064/com.example.android.dessertclicker D/MainActivity: onStart Called
2020-10-16 10:42:18.158 22064-22064/com.example.android.dessertclicker D/MainActivity: onResume Called

Lorsque l'activité revient au premier plan, la méthode onCreate() n'est pas rappelée. L'objet d'activité n'a pas été détruit. Il n'a donc pas besoin d'être créé à nouveau. Au lieu d'onCreate(), la méthode onRestart() est appelée. Notez que cette fois, lorsque l'activité revient au premier plan, le nombre de Desserts Sold (desserts vendus) est conservé.

  1. Lancez au moins une application autre que DessertClicker afin que l'écran de l'appareil affiche quelques applications récentes.
  2. Affichez l'écran des actions récentes et ouvrez une autre activité récente. Revenez ensuite aux applications récentes et remettez DessertClicker au premier plan.

Notez que les mêmes rappels s'affichent ici dans Logcat que lorsque vous avez appuyé sur le bouton Accueil. onPause() et onStop() sont appelés lorsque l'application passe en arrière-plan, puis onRestart(), onStart() et onResume() lorsqu'elle revient au premier plan.

Ces méthodes sont appelées lorsque l'application est arrêtée et qu'elle passe en arrière-plan, ou lorsqu'elle est redémarrée et qu'elle revient au premier plan. Si vous devez effectuer une tâche dans votre application dans ces situations, remplacez la méthode de rappel de cycle de vie appropriée.

Qu'en est-il de la méthode onRestart() ? La méthode onRestart() est semblable à onCreate(). onCreate() ou onRestart() est appelé avant que l'activité ne soit visible. La méthode onCreate() n'est appelée que la première fois, puis c'est onRestart() qui est appelé par la suite. La méthode onRestart() vous permet d'insérer du code que vous ne souhaitez appeler que si votre activité n'est pas démarrée pour la première fois.

Cas d'utilisation 3 : Masquer partiellement l'activité

Vous avez vu que lorsqu'une application est démarrée et que la méthode onStart() est appelée, l'application devient visible à l'écran. Lorsque cette dernière est réactivée et que l'élément onResume() est appelé, elle reçoit toute l'attention de l'utilisateur. Autrement dit, il peut interagir avec elle. La partie du cycle de vie dans laquelle l'application est entièrement affichée à l'écran et axée sur l'utilisateur est appelée cycle de vie interactif.

Lorsque l'application passe en arrière-plan, elle n'est plus le centre d'attention après onPause() et n'est plus visible après onStop().

La différence entre l'attention et la visibilité est importante, car il est possible qu'une activité soit partiellement visible à l'écran, sans qu'elle n'ait l'attention de l'utilisateur. Au cours de cette étape, vous allez examiner un cas où une activité est partiellement visible, sans avoir l'attention de l'utilisateur.

  1. Après avoir exécuté l'application DessertClicker, cliquez sur le bouton Share (Partager) en haut à droite de l'écran.

L'activité de partage apparaît dans la moitié inférieure de l'écran, mais votre activité reste visible dans la moitié supérieure.

e2319779260eb5ee.png

9ddc8b1dc79b1bff.png

  1. Examinez Logcat et notez que seul onPause() a été appelé.
2020-10-16 11:00:53.857 22064-22064/com.example.android.dessertclicker D/MainActivity: onPause Called

Dans ce cas d'utilisation, onStop() n'est pas appelé, car l'activité est encore partiellement visible. Toutefois, l'activité ne reçoit pas l'attention de l'utilisateur. Celui-ci ne peut donc pas interagir avec elle. L'activité de partage qui est au premier plan est axée sur l'utilisateur.

Pourquoi cette différence est-elle importante ? L'interruption avec onPause() uniquement dure peu de temps avant de revenir à votre activité ou d'accéder à une autre activité ou application. Il est généralement conseillé de continuer à mettre à jour l'interface utilisateur pour que le reste de votre application ne semble pas se figer.

Le code exécuté dans onPause() empêche l'affichage d'autres éléments. Par conséquent, n'abusez pas de l'utilisation de l'élément onPause(). Par exemple, si un appel téléphonique arrive, le code dans onPause() peut retarder la notification de l'appel entrant.

  1. Cliquez en dehors de la boîte de dialogue de partage pour revenir à l'application. Vous remarquerez que l'élément onResume() est appelé.

onResume() et onPause() sont tous deux liés à l'attention. La méthode onResume() est appelée lorsque l'activité reçoit l'attention de l'utilisateur, tandis que la méthode onPause() est appelée lorsque l'activité la perd.

5. Explorer les modifications de la configuration

Il est important de connaître un autre cas de figure dans la gestion du cycle de vie de l'activité : l'impact des modifications de la configuration sur le cycle de vie de vos activités.

Une modification de la configuration se produit lorsque l'état de l'appareil change de manière si radicale que le moyen le plus simple de s'adapter à cette modification consiste à arrêter complètement l'activité et à la recréer. Par exemple, si l'utilisateur change la langue de l'appareil, la mise en page devra peut-être changer pour s'adapter aux différentes orientations de texte et longueurs de chaînes. Si l'utilisateur branche l'appareil sur une station d'accueil ou ajoute un clavier physique, l'application devra peut-être s'ajuster à un changement de taille d'écran ou de mise en page. Enfin, si l'orientation de l'appareil change (s'il passe du mode portrait au mode paysage ou inversement), la mise en page peut avoir besoin d'être modifiée pour s'adapter à la nouvelle orientation. Voyons le comportement de l'application dans ce scénario.

Perte de données lors de la rotation de l'appareil

  1. Compilez et exécutez votre application, puis ouvrez Logcat.
  2. Faites pivoter l'appareil ou l'émulateur en mode Paysage. Vous pouvez faire pivoter l'émulateur vers la gauche ou vers la droite à l'aide des boutons de rotation, ou avec Control et les touches fléchées (Command et les touches fléchées sur Mac). 623fce7c623d42bd.png
  3. Examinez la sortie dans Logcat. Filtrez la sortie sur MainActivity.
2020-10-16 11:03:09.618 23206-23206/com.example.android.dessertclicker D/MainActivity: onCreate Called
2020-10-16 11:03:09.806 23206-23206/com.example.android.dessertclicker D/MainActivity: onStart Called
2020-10-16 11:03:09.808 23206-23206/com.example.android.dessertclicker D/MainActivity: onResume Called
2020-10-16 11:03:24.488 23206-23206/com.example.android.dessertclicker D/MainActivity: onPause Called
2020-10-16 11:03:24.490 23206-23206/com.example.android.dessertclicker D/MainActivity: onStop Called
2020-10-16 11:03:24.493 23206-23206/com.example.android.dessertclicker D/MainActivity: onDestroy Called
2020-10-16 11:03:24.520 23206-23206/com.example.android.dessertclicker D/MainActivity: onCreate Called
2020-10-16 11:03:24.569 23206-23206/com.example.android.dessertclicker D/MainActivity: onStart Called

Notez que lorsque l'appareil ou l'émulateur fait pivoter l'écran, le système appelle tous les rappels de cycle de vie afin d'arrêter l'activité. Ensuite, lorsque l'activité est recréée, le système appelle tous les rappels de cycle de vie pour la démarrer.

  1. Lors de la rotation de l'appareil, et lorsque l'activité est arrêtée et recréée, celle-ci démarre avec des valeurs par défaut : le nombre de desserts vendus et les revenus sont remis à zéro.

Enregistrer les données du bundle à l'aide de la fonction onSaveInstanceState()

La méthode onSaveInstanceState() est un rappel qui permet d'enregistrer les données dont vous pourriez avoir besoin si l'activité (Activity) était éliminée. Dans le schéma de rappel de cycle de vie, onSaveInstanceState() est appelé après l'arrêt de l'activité. Il est appelé chaque fois que votre application passe en arrière-plan.

c259ab6beca0ca88.png

Considérez l'appel onSaveInstanceState() comme une mesure de sécurité. Il vous donne l'occasion d'enregistrer un petit volume d'informations dans un bundle lorsque votre activité quitte le premier plan. Le système enregistre ces données à ce stade, car s'il attendait que votre application s'arrête, il pourrait manquer de ressources.

En enregistrant les données à chaque fois, vous garantissez que les données mises à jour dans le bundle peuvent être restaurées, si nécessaire.

  1. Dans MainActivity, remplacez le rappel onSaveInstanceState() et ajoutez une instruction de journalisation.
override fun onSaveInstanceState(outState: Bundle) {
   super.onSaveInstanceState(outState)

   Log.d(TAG, "onSaveInstanceState Called")
}
  1. Compilez et exécutez l'application, puis cliquez sur le bouton Accueil pour la mettre en arrière-plan. Notez que le rappel onSaveInstanceState() se produit juste après onPause() et onStop() :
2020-10-16 11:05:21.726 23415-23415/com.example.android.dessertclicker D/MainActivity: onPause Called
2020-10-16 11:05:22.382 23415-23415/com.example.android.dessertclicker D/MainActivity: onStop Called
2020-10-16 11:05:22.393 23415-23415/com.example.android.dessertclicker D/MainActivity: onSaveInstanceState Called
  1. En haut du fichier, juste avant la définition de classe, ajoutez les constantes suivantes :
const val KEY_REVENUE = "revenue_key"
const val KEY_DESSERT_SOLD = "dessert_sold_key"

Vous utiliserez ces clés pour enregistrer et récupérer les données du bundle d'états d'instance.

  1. Faites défiler la page jusqu'à onSaveInstanceState() et notez le paramètre outState, qui est de type Bundle. Un Bundle est un ensemble de paires clé-valeur, où les clés correspondent toujours à des chaînes. Vous pouvez placer des données simples, telles que des valeurs Int et Boolean, dans le bundle. Comme le système conserve ce bundle en mémoire, il est recommandé de limiter la quantité de données qu'il contient. La taille de ce bundle est également limitée, même si elle varie d'un appareil à l'autre. Si vous stockez trop de données, vous risquez de faire planter votre application et de générer l'erreur TransactionTooLargeException.
  2. Dans onSaveInstanceState(), placez la valeur revenue (un entier) dans le bundle avec la méthode putInt() :
outState.putInt(KEY_REVENUE, revenue)

La méthode putInt() (et les méthodes similaires de la classe Bundle comme putFloat() et putString()) utilise deux arguments : une chaîne pour la clé (la constante KEY_REVENUE) et la valeur réelle à enregistrer.

  1. Suivez la même procédure avec le nombre de desserts vendus :
outState.putInt(KEY_DESSERT_SOLD, dessertsSold)

Restaurer les données d'un bundle à l'aide de la méthode onCreate()

L'état de l'activité peut être restauré dans onCreate(Bundle) ou onRestoreInstanceState(Bundle) (le Bundle renseigné par la méthode onSaveInstanceState() sera transmis aux deux méthodes de rappel de cycle de vie).

  1. Faites défiler la page jusqu'à onCreate() et examinez la signature de la méthode :
override fun onCreate(savedInstanceState: Bundle?) {

Notez qu'onCreate() reçoit un Bundle à chaque appel. Lorsque votre activité redémarre après l'arrêt d'un processus, le bundle que vous avez enregistré est transmis à onCreate(). Si l'activité recommençait à zéro, ce Bundle dans onCreate() serait null. Si le bundle n'est pas null, vous savez que vous "recréez" l'activité à partir d'un point précédent connu.

  1. Ajoutez ce code à onCreate(), juste après la définition de la variable binding :
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
}

Le test pour null détermine si le bundle contient des données ou s'il est null, ce qui vous indique si l'application a été démarrée de zéro ou a été recréée après un arrêt. Ce test est un modèle courant de restauration des données du bundle.

Notez que la clé que vous avez utilisée ici (KEY_REVENUE) est la même que celle que vous avez utilisée pour putInt(). Pour vous assurer d'employer la même clé à chaque fois, il est recommandé de définir ces clés comme constantes. Utilisez getInt() pour extraire des données du bundle, tout comme vous avez utilisé putInt() pour y placer des données. La méthode getInt() comporte deux arguments :

  • Une chaîne servant de clé, par exemple "key_revenue" pour la valeur des revenus.
  • Une valeur par défaut si aucune valeur n'existe pour cette clé dans le bundle

L'entier que vous obtenez du bundle est ensuite attribué à la variable revenue. L'UI utilise cette valeur.

  1. Ajoutez des méthodes getInt() pour redresser le chiffre d'affaires et le nombre de desserts vendus.
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
   dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
}
  1. Compilez et exécutez l'application. Appuyez sur le cupcake au moins cinq fois jusqu'à obtenir un beignet.
  2. Faites pivoter l'appareil. Notez que cette fois, l'application affiche les valeurs de bundle correctes pour les revenus et les desserts vendus. Notez aussi que le dessert est à nouveau un cupcake. 4179956182ffc634.png

Il vous reste une dernière chose à faire pour vous assurer que l'application revient exactement là où elle s'était arrêtée.

  1. Dans MainActivity, examinez la méthode showCurrentDessert(). Notez qu'elle détermine l'image de dessert à afficher dans l'activité en fonction du nombre actuel de desserts vendus et de la liste de desserts dans la variable allDesserts.
for (dessert in allDesserts) {
   if (dessertsSold >= dessert.startProductionAmount) {
       newDessert = dessert
   }
    else break
}

Cette méthode s'appuie sur le nombre de desserts vendus pour choisir la bonne image. Vous n'avez donc rien à faire pour référencer une image dans le bundle dans onSaveInstanceState(). Dans ce bundle, vous stockez déjà le nombre de desserts vendus.

  1. Dans onCreate(), dans le bloc qui restaurera l'état du bundle, appelez showCurrentDessert() :
 if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
   dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
   showCurrentDessert()
}
  1. Compilez et exécutez l'application, puis faites pivoter l'écran. Notez que les valeurs des desserts vendus, le total des revenus et l'image du dessert sont correctement restaurés.

6. Résumé

Cycle de vie de l'activité

  • Le cycle de vie de l'activité correspond à un ensemble d'états par lesquels passe une activité. Il commence lorsque l'activité est créée pour la première fois et se termine lorsque l'activité est éliminée.
  • Lorsque l'utilisateur passe d'une activité à l'autre et de votre application à une autre, l'état change dans le cycle de vie de l'activité.
  • Chaque état du cycle de vie de l'activité possède une méthode de rappel correspondante que vous pouvez remplacer dans la classe Activity. Les principales méthodes de cycle de vie sont les suivantes : onCreate()onStart()onPause()onRestart()onResume()onStop()onDestroy()
  • Pour ajouter le comportement qui se produit lorsque votre activité passe à un état du cycle de vie, remplacez la méthode de rappel correspondante.
  • Pour ajouter des méthodes de remplacement à vos classes dans Android Studio, sélectionnez Code > Remplacer les méthodes ou appuyez sur Control+o.

Journalisation

  • L'API de journalisation Android, et plus particulièrement la classe Log, vous permet d'écrire des messages courts affichés dans l'outil Logcat dans Android Studio.
  • Utilisez Log.d() pour rédiger un message de débogage. Cette méthode utilise deux arguments : la balise de journal (généralement un nom de classe) et le message de journal (une courte chaîne).
  • Utilisez la fenêtre Logcat d'Android Studio pour afficher les journaux système, y compris les messages que vous écrivez.

Conserver l'état de l'activité

  • Lorsque votre application passe en arrière-plan, juste après l'appel de la méthode onStop(), les données de l'application peuvent être enregistrées dans un bundle. Certaines données de l'application, telles que le contenu d'un élément EditText, sont automatiquement enregistrées.
  • Le bundle est une instance de Bundle, qui correspond à un ensemble de clés et de valeurs. Les clés sont toujours des chaînes.
  • Utilisez le rappel onSaveInstanceState() pour enregistrer d'autres données dans le bundle que vous souhaitez conserver, même si l'application a été fermée automatiquement. Pour placer des données dans le bundle, utilisez les méthodes correspondantes commençant par put, telles que putInt().
  • Vous pouvez récupérer des données du bundle dans la méthode onRestoreInstanceState() ou, plus communément, dans onCreate(). La méthode onCreate() comporte un paramètre savedInstanceState qui détient le bundle.
  • Si la variable savedInstanceState est null, l'activité a été lancée sans bundle d'état et il n'existe pas de données d'état à récupérer.
  • Pour récupérer des données du bundle avec une clé, utilisez les méthodes Bundle commençant par get, par exemple getInt().

Modifications de la configuration

  • Une modification de la configuration se produit lorsque l'état de l'appareil change de manière si radicale que le moyen le plus simple de s'adapter à cette modification consiste à éliminer l'activité et à la recréer.
  • L'exemple le plus courant de modification de la configuration est lorsque l'utilisateur fait pivoter l'appareil du mode Portrait au mode Paysage, ou inversement. Une modification de la configuration peut également se produire lorsque la langue de l'appareil change ou qu'un clavier matériel est branché.
  • Lorsqu'une modification de configuration se produit, Android appelle tous les rappels d'arrêt du cycle de vie de l'activité. Android redémarre ensuite toute l'activité, en exécutant tous les rappels de démarrage du cycle de vie.
  • Quand Android arrête une application en raison d'une modification de la configuration, il redémarre l'activité avec le bundle d'état disponible pour onCreate().
  • Comme pour l'arrêt d'un processus, enregistrez l'état de votre application dans le bundle dans onSaveInstanceState().

7. En savoir plus