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.
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
- Cliquez sur l'URL indiquée. La page GitHub du projet s'ouvre dans un navigateur.
- Sur la page GitHub du projet, cliquez sur le bouton Code pour afficher une boîte de dialogue.
- 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.
- Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
- 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
- Lancez Android Studio.
- 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).
Remarque : Si Android Studio est déjà ouvert, sélectionnez l'option de menu File > New > Import Project (Fichier > Nouveau > Importer un projet).
- 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.
- Double-cliquez sur le dossier de ce projet.
- Attendez qu'Android Studio ouvre le projet.
- Cliquez sur le bouton Run (Exécuter) pour créer et exécuter l'application. Assurez-vous qu'elle fonctionne correctement.
- 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.
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é.
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.
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.
- 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.
- Ouvrez
MainActivity.kt
et examinez la méthodeonCreate()
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.
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.
- Dans la méthode
onCreate()
, juste après l'appel desuper.onCreate()
, ajoutez la ligne suivante :
Log.d("MainActivity", "onCreate Called")
- Importez la classe
Log
si nécessaire (appuyez surAlt+Enter
ouOption+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 classeLog
incluentLog.i()
pour les messages d'information,Log.e()
pour les erreurs,Log.w()
pour les avertissements ouLog.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.
- 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.
- Dans la fenêtre Logcat, saisissez
D/MainActivity
dans le champ de recherche.
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é.
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.
- Dans Android Studio, lorsque
MainActivity.kt
est ouvert et que le curseur se trouve dans la classeMainActivity
, sélectionnez Code > Override Methods (Ignorer les méthodes) ou appuyez surControl+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.
- 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électionnezonStart()
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()
}
- 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"
- Dans la méthode
onStart()
, ajoutez un message de journal :
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart Called")
}
- 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éthodesonCreate()
etonStart()
ont été appelées l'une après l'autre, et que votre activité est visible à l'écran. - 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éthodeonCreate()
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.
- 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")
}
- Compilez et exécutez à nouveau DessertClicker, puis examinez Logcat. Cette fois, vous remarquerez qu'en plus des éléments
onCreate()
etonStart()
, il existe un message de journal pour le rappel du cycle de vieonResume()
.
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'applicationonStart()
pour la démarrer et l'afficher à l'écranonResume()
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.
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.
- 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()
etonResume()
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
- Appuyez plusieurs fois sur le cupcake.
- Appuyez sur le bouton Retour de l'appareil. Notez que dans Logcat,
onPause()
,onStop()
etonDestroy()
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.
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.
- 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.
- Après avoir exécuté l'application DessertClicker, cliquez plusieurs fois sur le cupcake.
- 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()
etonStop()
sont appelées, mais pasonDestroy()
.
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é.
- Utilisez l'écran des actions récentes pour revenir à l'application. Notez que dans Logcat, l'activité est redémarrée avec
onRestart()
etonStart()
, puis réactivée aveconResume()
.
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é.
- Lancez au moins une application autre que DessertClicker afin que l'écran de l'appareil affiche quelques applications récentes.
- 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.
- 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.
- 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.
- 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
- Compilez et exécutez votre application, puis ouvrez Logcat.
- 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). - 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.
- 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.
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.
- Dans
MainActivity
, remplacez le rappelonSaveInstanceState()
et ajoutez une instruction de journalisation.
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
Log.d(TAG, "onSaveInstanceState Called")
}
- 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èsonPause()
etonStop()
:
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
- 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.
- Faites défiler la page jusqu'à
onSaveInstanceState()
et notez le paramètreoutState
, qui est de typeBundle
. UnBundle
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 valeursInt
etBoolean
, 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'erreurTransactionTooLargeException
. - Dans
onSaveInstanceState()
, placez la valeurrevenue
(un entier) dans le bundle avec la méthodeputInt()
:
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.
- 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).
- 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.
- Ajoutez ce code à
onCreate()
, juste après la définition de la variablebinding
:
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.
- 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)
}
- Compilez et exécutez l'application. Appuyez sur le cupcake au moins cinq fois jusqu'à obtenir un beignet.
- 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.
Il vous reste une dernière chose à faire pour vous assurer que l'application revient exactement là où elle s'était arrêtée.
- Dans
MainActivity
, examinez la méthodeshowCurrentDessert()
. 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 variableallDesserts
.
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.
- Dans
onCreate()
, dans le bloc qui restaurera l'état du bundle, appelezshowCurrentDessert()
:
if (savedInstanceState != null) {
revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
showCurrentDessert()
}
- 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émentEditText
, 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 parput
, telles queputInt()
. - Vous pouvez récupérer des données du bundle dans la méthode
onRestoreInstanceState()
ou, plus communément, dansonCreate()
. La méthodeonCreate()
comporte un paramètresavedInstanceState
qui détient le bundle. - Si la variable
savedInstanceState
estnull
, 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 parget
, par exemplegetInt()
.
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()
.