Kotlin Fundamentals 05.2: LiveData et LiveObservers d'Android

Cet atelier de programmation fait partie du cours Android Kotlin Fundamentals. Vous tirerez le meilleur parti de ce cours si vous suivez les ateliers de programmation dans l'ordre. Tous les ateliers de programmation du cours sont répertoriés sur la page de destination des ateliers de programmation Android Kotlin Fundamentals.

Présentation

Dans l'atelier de programmation précédent, vous avez utilisé un ViewModel dans l'application GuessTheWord pour permettre aux données de l'application de survivre aux modifications de configuration de l'appareil. Dans cet atelier de programmation, vous allez apprendre à intégrer LiveData aux données des classes ViewModel. LiveData, l'un des composants d'architecture Android, vous permet de créer des objets de données qui avertissent les vues lorsque la base de données sous-jacente est modifiée.

Pour utiliser la classe LiveData, vous devez configurer des"observateurs" (par exemple, des activités ou des fragments) qui observent des changements dans les données de l'application. LiveData tient compte du cycle de vie, il ne met donc à jour que les observateurs de composants d'application qui sont actifs.

Ce que vous devez déjà savoir

  • Créer des applications Android de base en Kotlin
  • Comment parcourir les destinations de votre application
  • Cycle de vie des activités et des fragments.
  • Utiliser les objets ViewModel dans votre application
  • Créer des objets ViewModel à l'aide de l'interface ViewModelProvider.Factory

Points abordés

  • Objets LiveData utiles.
  • Comment ajouter LiveData aux données stockées dans un ViewModel.
  • Quand et comment utiliser MutableLiveData
  • Ajouter des méthodes d'observation afin d'observer les changements dans la LiveData.
  • Comment encapsuler LiveData à l'aide d'une propriété de support.
  • Communication entre un contrôleur d'interface utilisateur et le ViewModel correspondant

Objectifs de l'atelier

  • Utilisez LiveData pour le mot et le score dans l'application GuessTheWord.
  • Ajoutez des observateurs qui remarqueront la modification du mot ou du score.
  • Mettez à jour les vues de texte qui affichent les valeurs modifiées.
  • Utilisez le schéma d'observateur LiveData pour ajouter un événement terminé.
  • Intégrez le bouton Play Again (Rejouer).

Dans les ateliers de programmation de la leçon 5, vous allez développer l'application GuessTheWord en commençant par le code de démarrage. GuessTheWord est un jeu de charades à deux joueurs, où les joueurs collaborent pour obtenir le meilleur score possible.

Le premier joueur analyse les mots dans l'application et les joue tous à tour de rôle. Veillez donc à ne pas afficher le mot au deuxième joueur. Le deuxième joueur essaie de deviner le mot.

Pour lancer ce jeu, le premier joueur ouvre l'application sur l'appareil et voit un mot, par exemple "guitare", comme illustré dans la capture d'écran ci-dessous.

Le premier joueur joue le mot, en prenant soin de ne pas le prononcer.

  • Lorsque le deuxième joueur essaie de deviner le mot, le premier appuie sur le bouton OK, ce qui augmente le nombre de points et affiche le mot suivant.
  • S'il ne parvient pas à deviner le mot, le premier joueur appuie sur le bouton Ignorer, ce qui diminue le nombre de fois jusqu'à l'affichage du mot suivant.
  • Pour terminer la partie, appuyez sur le bouton Terminer le jeu. (Cette fonctionnalité n'est pas disponible dans le code de démarrage du premier atelier de programmation de cette série.)

Dans cet atelier de programmation, vous allez améliorer l'application GuessTheWord en ajoutant un événement pour terminer le jeu lorsque l'utilisateur fait défiler les mots dans l'application. Vous ajoutez également un bouton Play Again (Rejouer) dans le fragment de score, pour que l'utilisateur puisse rejouer.

Écran titre

Écran de jeu

Écran de score

Dans cette tâche, vous allez localiser et exécuter le code de démarrage de cet atelier de programmation. Vous pouvez utiliser l'application GuessTheWord que vous avez créée dans l'atelier de programmation précédent comme code de démarrage. Vous pouvez également en télécharger une.

  1. (Facultatif) Si vous n'utilisez pas le code de l'atelier de programmation précédent, téléchargez-le. Décompressez le code, puis ouvrez le projet dans Android Studio.
  2. Exécutez l'application et jouez au jeu.
  3. Notez que le bouton Ignorer affiche le mot suivant et diminue le score de 1. Le bouton OK permet d'afficher le mot suivant et d'augmenter le score de 1. Le bouton Terminer le jeu met fin au jeu.

LiveData est une classe de conteneur de données observable qui tient compte du cycle de vie. Par exemple, vous pouvez encapsuler un LiveData autour du score actuel dans l'application GuessTheWord : dans cet atelier de programmation, vous allez découvrir plusieurs caractéristiques de LiveData :

  • LiveData est observable, ce qui signifie qu'un observateur est averti lorsque les données conservées par l'objet LiveData sont modifiées.
  • LiveData contient des données ; LiveData est un wrapper qui peut être utilisé avec toutes les données
  • LiveData tient compte du cycle de vie, c'est-à-dire qu'il ne met à jour que les observateurs qui sont actifs dans leur cycle de vie (STARTED ou RESUMED, par exemple).

Dans cette tâche, vous allez apprendre à encapsuler un type de données dans des objets LiveData en convertissant le score et les données de mots actuels dans GameViewModel dans LiveData. Plus tard, vous ajouterez un observateur à ces objets LiveData et apprendrez à observer LiveData.

Étape 1: Modifiez le score et le mot pour utiliser LiveData

  1. Sous le package screens/game, ouvrez le fichier GameViewModel.
  2. Remplacez le type des variables score et word par MutableLiveData.

    MutableLiveData est un LiveData dont la valeur peut être modifiée. MutableLiveData est une classe générique. Vous devez donc spécifier le type de données qu'elle contient.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
  1. Dans GameViewModel, dans le bloc init, initialisez score et word. Pour modifier la valeur d'une variable LiveData, utilisez la méthode setValue() sur cette variable. En langage Kotlin, vous pouvez appeler setValue() à l'aide de la propriété value.
init {

   word.value = ""
   score.value = 0
  ...
}

Étape 2: Mettez à jour la référence de l'objet LiveData

Les variables score et word sont désormais de type LiveData. Au cours de cette étape, vous allez modifier les références à ces variables à l'aide de la propriété value.

  1. Dans GameViewModel, dans la méthode onSkip(), remplacez score par score.value. Vous remarquerez qu'il s'agit probablement d'une erreur null pour score. Vous allez corriger cette erreur ensuite.
  2. Pour résoudre l'erreur, ajoutez une vérification null à score.value dans onSkip(). Appelez ensuite la fonction minus() sur score, qui effectue la soustraction avec null-safety.
fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}
  1. Mettez à jour la méthode onCorrect() de la même manière: ajoutez une vérification null à la variable score et utilisez la fonction plus().
fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}
  1. Dans GameViewModel, dans la méthode nextWord(), remplacez la référence word par word.value.
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}
  1. Dans GameFragment, dans la méthode updateWordText(), remplacez la référence par viewModel.word par viewModel.word.value.
/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}
  1. Dans GameFragment, dans la méthode updateScoreText(), remplacez la référence par viewModel.score par viewModel.score.value.
private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}
  1. Dans GameFragment, dans la méthode gameFinished(), remplacez la référence par viewModel.score par viewModel.score.value. Ajoutez le contrôle de sécurité null requis.
private fun gameFinished() {
   Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
   val action = GameFragmentDirections.actionGameToScore()
   action.score = viewModel.score.value?:0
   NavHostFragment.findNavController(this).navigate(action)
}
  1. Vérifiez que votre code ne contient pas d'erreurs. Compilez et exécutez votre application. La fonctionnalité de l'application doit être identique à celle utilisée précédemment.

Cette tâche est étroitement liée à la tâche précédente, qui consiste à convertir les données de score et de mots en objets LiveData. Dans cette tâche, vous allez associer des objets Observer à ces objets LiveData.

  1. Dans la GameFragment, de la méthode onCreateView(), associez un objet Observer à l'objet LiveData pour obtenir le score actuel, viewModel.score. Utilisez la méthode observe() et insérez le code après l'initialisation de viewModel. Utilisez une expression lambda pour simplifier le code. (Une expression lambda est une fonction anonyme qui n'est pas déclarée, mais qui est transmise immédiatement en tant qu'expression.
viewModel.score.observe(this, Observer { newScore ->
})

Résolvez la référence à Observer. Pour ce faire, cliquez sur Observer, appuyez sur Alt+Enter (Option+Enter sur un Mac), puis importez androidx.lifecycle.Observer.

  1. L'observateur que vous venez de créer reçoit un événement lorsque les données conservées par l'objet LiveData observé sont modifiées. Dans l'observateur, mettez à jour le score TextView avec le nouveau score.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. Associez un objet Observer à l'objet de mot LiveData actuel. Procédez de la même manière que vous associez un objet Observer au score actuel.
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})

Lorsque la valeur de score ou de word change, l'élément score ou word affiché à l'écran est désormais mis à jour automatiquement.

  1. Dans GameFragment, supprimez les méthodes updateWordText() et updateScoreText(), ainsi que toutes les références à celles-ci. Vous n'en avez plus besoin, car les vues de texte sont mises à jour par les méthodes d'observation LiveData.
  2. Exécutez votre application. Votre application de jeu devrait fonctionner exactement comme auparavant, mais elle utilise désormais LiveData et des observateurs LiveData.

L'encapsulation permet de restreindre l'accès direct à certains champs des objets. Lorsque vous encapsulez un objet, vous exposez un ensemble de méthodes publiques qui modifient les champs internes privés. L'encapsulation vous permet de contrôler la façon dont les autres classes manipulent ces champs internes.

Dans votre code actuel, toute classe externe peut modifier les variables score et word à l'aide de la propriété value, par exemple en utilisant viewModel.score.value. Peu importe l'application que vous développez dans cet atelier de programmation, mais dans une application en production, vous voulez contrôler les données des objets ViewModel.

Seul le ViewModel doit modifier les données de votre appli. Toutefois, les contrôleurs de l'interface utilisateur doivent lire les données, et les champs de données ne peuvent donc pas être totalement privés. Pour encapsuler les données de votre application, vous devez utiliser les objets MutableLiveData et LiveData.

MutableLiveData et LiveData :

  • Les données d'un objet MutableLiveData peuvent être modifiées, comme son nom l'indique. Dans ViewModel, les données doivent être modifiables. Elles utilisent donc MutableLiveData.
  • Les données d'un objet LiveData peuvent être lues, mais pas modifiées. En dehors de ViewModel, les données doivent être lisibles, mais pas modifiables. Elles doivent donc être exposées en tant que LiveData.

Pour mettre en œuvre cette stratégie, vous utilisez une propriété de support Kotlin. Une propriété de support vous permet de renvoyer un élément à partir d'un getter autre que l'objet exact. Dans cette tâche, vous allez implémenter une propriété de support pour les objets score et word dans l'application GuessTheWord.

Ajouter une propriété de support pour le score et le mot

  1. Dans GameViewModel, définissez l'objet score actuel private.
  2. Pour respecter la convention d'attribution de noms utilisée dans les propriétés de support, remplacez score par _score. La propriété _score est désormais la version modifiable du score de jeu, qui doit être utilisée en interne.
  3. Créez une version publique du type LiveData, appelée score.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
  1. Une erreur d'initialisation s'affiche. Cette erreur se produit, car au sein de GameFragment, score est une référence LiveData, et score ne peut plus accéder à son setter. Pour en savoir plus sur les getters et les setters en langage Kotlin, consultez la section Getters et setters.

    Pour résoudre l'erreur, ignorez la méthode get() pour l'objet score dans GameViewModel, puis renvoyez la propriété de support _score.
val score: LiveData<Int>
   get() = _score
  1. Dans GameViewModel, remplacez les références de score par sa version modifiable interne, _score.
init {
   ...
   _score.value = 0
   ...
}

...
fun onSkip() {
   if (!wordList.isEmpty()) {
       _score.value = (score.value)?.minus(1)
   }
  ...
}

fun onCorrect() {
   if (!wordList.isEmpty()) {
       _score.value = (score.value)?.plus(1)
   }
   ...
}
  1. Renommez l'objet word en _word et ajoutez une propriété de support, comme vous l'avez fait pour l'objet score.
// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
   get() = _word
...
init {
   _word.value = ""
   ...
}
...
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       _word.value = wordList.removeAt(0)
   }
}

Bien joué, vous avez encapsulé les objets LiveData word et score.

Votre application actuelle accède à l'écran de score lorsque l'utilisateur appuie sur le bouton End Game (Terminer le jeu). Vous voulez également que l'application accède à l'écran de score lorsque les joueurs ont parcouru tous les mots en même temps. Une fois que le joueur a terminé avec le dernier mot, le jeu doit se terminer automatiquement. L'utilisateur n'a donc pas besoin d'appuyer sur le bouton.

Pour implémenter cette fonctionnalité, vous devez déclencher un événement et communiquer au fragment à partir du ViewModel lorsque tous les mots ont été affichés. Pour ce faire, vous utilisez le modèle d'observateur LiveData pour modéliser un événement terminé.

Schéma d'observateur

Le modèle d'observateur est un modèle de conception logicielle. Il spécifie la communication entre les objets, un observable (l'objet d'observation) et des observateurs. Un observable est un objet qui informe les observateurs des modifications de son état.

Dans le cas de LiveData dans cette application, l'observable (l'objet) est l'objet LiveData, et les observateurs sont les méthodes des contrôleurs de l'interface utilisateur, comme les fragments. Un état est modifié chaque fois que les données encapsulées dans LiveData changent. Les classes LiveData sont essentielles pour communiquer entre le ViewModel et le fragment.

Étape 1: Utilisez LiveData pour détecter un événement terminé dans le jeu

Dans cette tâche, vous allez utiliser le modèle d'observateur LiveData pour modéliser un événement terminé.

  1. Dans GameViewModel, créez un objet Boolean MutableLiveData appelé _eventGameFinish. Cet objet contient l'événement de jeu terminé.
  2. Après avoir initialisé l'objet _eventGameFinish, créez et initialisez une propriété de support appelée eventGameFinish.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
   get() = _eventGameFinish
  1. Dans GameViewModel, ajoutez une méthode onGameFinish(). Dans la méthode, définissez l'événement terminé dans le jeu eventGameFinish sur true.
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. Dans GameViewModel, dans la méthode nextWord(), mettez fin au jeu si la liste de mots est vide.
private fun nextWord() {
   if (wordList.isEmpty()) {
       onGameFinish()
   } else {
       //Select and remove a _word from the list
       _word.value = wordList.removeAt(0)
   }
}
  1. Dans GameFragment, dans onCreateView(), après avoir initialisé viewModel, ajoutez un observateur à eventGameFinish. Utilisez la méthode observe(). Dans le lambda, appelez la méthode gameFinished().
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
   if (hasFinished) gameFinished()
})
  1. Exécutez votre application, jouez au jeu et parcourez tous les mots. L'application affiche l'écran de score automatiquement au lieu de rester dans le fragment du jeu jusqu'à ce que vous appuyiez sur Arrêter le jeu.

    Une fois la liste de mots vide, eventGameFinish est défini. La méthode d'observation associée dans le fragment de jeu est appelée, et l'application accède au fragment d'écran.
  2. Le code que vous avez ajouté a introduit un problème de cycle de vie. Pour comprendre le problème, commentez le code de navigation dans la méthode gameFinished() dans la classe GameFragment. Veillez à conserver le message Toast dans la méthode.
private fun gameFinished() {
       Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
//        val action = GameFragmentDirections.actionGameToScore()
//        action.score = viewModel.score.value?:0
//        NavHostFragment.findNavController(this).navigate(action)
   }
  1. Exécutez votre application, jouez au jeu et parcourez tous les mots. Le message "Le jeu vient d'être terminé" s'affiche brièvement en bas de l'écran, ce qui est normal.

Faites pivoter l'appareil ou l'émulateur. Le pain grillé s'affiche à nouveau ! Faites pivoter l'appareil plusieurs fois. Vous verrez probablement le pain grillé à chaque fois. Il s'agit d'un bug, car le pain perdu ne s'affiche qu'une seule fois, une fois le jeu terminé. Le toast doit s'afficher chaque fois que le fragment est recréé. Vous pourrez résoudre ce problème à la tâche suivante.

Étape 2: Réinitialisez l'événement terminé

Généralement, LiveData ne transmet les mises à jour aux observateurs que lorsque les données changent. Il existe toutefois une exception à ce comportement : les observateurs reçoivent également des mises à jour lorsqu'ils passent d'un état inactif à un état actif.

C'est pourquoi le toast terminé est déclenché de façon répétée dans votre application. Lorsque le fragment de jeu est recréé après une rotation de l'écran, il passe d'un état inactif à un état actif. L'observateur du fragment est reconnecté au ViewModel existant et reçoit les données actuelles. La méthode gameFinished() est déclenchée à nouveau, et le toast s'affiche.

Dans cette tâche, vous allez résoudre ce problème et afficher le toast une seule fois en réinitialisant l'indicateur eventGameFinish dans GameViewModel.

  1. Dans GameViewModel, ajoutez une méthode onGameFinishComplete() pour réinitialiser l'événement terminé dans le jeu, _eventGameFinish.
/** Method for the game completed event **/

fun onGameFinishComplete() {
   _eventGameFinish.value = false
}
  1. Dans GameFragment, à la fin de gameFinished(), appelez onGameFinishComplete() sur l'objet viewModel. (Laisser le code de navigation dans gameFinished() commenté pour l'instant.)
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. Exécutez l'application et jouez au jeu. Parcourez tous les mots, puis modifiez l'orientation de l'écran de l'appareil. Le pain perdu n'est affiché qu'une seule fois.
  2. Dans GameFragment, dans la méthode gameFinished(), annulez la mise en commentaire du code de navigation.

    Pour annuler la mise en commentaire dans Android Studio, sélectionnez les lignes commentées et appuyez sur Control+/ (Command+/ sur un Mac).
private fun gameFinished() {
   Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
   val action = GameFragmentDirections.actionGameToScore()
   action.score = viewModel.score.value?:0
   findNavController(this).navigate(action)
   viewModel.onGameFinishComplete()
}

Si Android Studio vous le demande, importez androidx.navigation.fragment.NavHostFragment.findNavController.

  1. Exécutez l'application et jouez au jeu. Assurez-vous que l'application accède automatiquement à l'écran du score final une fois que vous avez parcouru tous les mots.

Bien joué ! Votre application utilise LiveData pour déclencher un événement terminé dans le jeu afin de communiquer depuis le GameViewModel au fragment de jeu, indiquant que la liste de mots est vide. Le fragment de jeu accède ensuite au fragment de score.

Dans cette tâche, vous allez convertir le score en objet LiveData dans le ScoreViewModel et lui associer un observateur. Cette tâche est semblable à celle que vous avez effectuée lorsque vous avez ajouté LiveData à GameViewModel.

Vous devez effectuer les modifications suivantes dans ScoreViewModel. Ainsi, toutes les données de votre application utilisent LiveData.

  1. Dans ScoreViewModel, définissez le type de variable score sur MutableLiveData. Renommez-le par convention _score et ajoutez une propriété de support.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
   get() = _score
  1. Dans ScoreViewModel, dans le bloc init, initialisez _score. Vous pouvez supprimer ou supprimer le journal dans le bloc init comme vous le souhaitez.
init {
   _score.value = finalScore
}
  1. Dans ScoreFragment, dans onCreateView(), après avoir initialisé viewModel, joignez un observateur pour le score LiveData. Dans le lambda, définissez la valeur du score sur la vue textuelle du score. Supprimez le code qui attribue directement la vue Texte avec la valeur de score ViewModel.

Code à ajouter:

// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})

Code à supprimer:

binding.scoreText.text = viewModel.score.toString()

Lorsque Android Studio vous le demande, importez androidx.lifecycle.Observer.

  1. Exécutez votre application et jouez au jeu. L'application devrait fonctionner comme auparavant, mais elle utilise maintenant LiveData et un observateur pour mettre à jour le score.

Dans cette tâche, vous allez ajouter un bouton Play Again (Rejouer) à l'écran de score et implémenter son écouteur de clics à l'aide d'un événement LiveData. Ce bouton déclenche un événement de navigation entre l'écran de score et l'écran de jeu.

Le code de démarrage de l'application inclut le bouton Play Again (Rejouer), mais il est masqué.

  1. Dans res/layout/score_fragment.xml, pour le bouton play_again_button, remplacez la valeur de l'attribut visibility par visible.
<Button
   android:id="@+id/play_again_button"
...
   android:visibility="visible"
 />
  1. Dans ScoreViewModel, ajoutez un objet LiveData pour contenir un Boolean appelé _eventPlayAgain. Cet objet permet d'enregistrer l'événement LiveData pour passer de l'écran de score à l'écran de jeu.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. Dans ScoreViewModel, définissez les méthodes pour définir et réinitialiser l'événement, _eventPlayAgain.
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. Dans ScoreFragment, ajoutez un observateur pour eventPlayAgain. Placez le code à la fin de onCreateView(), avant l'instruction return. Dans le lambda, revenez à l'écran du jeu et réinitialisez eventPlayAgain.
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
   if (playAgain) {
      findNavController().navigate(ScoreFragmentDirections.actionRestart())
       viewModel.onPlayAgainComplete()
   }
})

Importez androidx.navigation.fragment.findNavController lorsque vous y êtes invité par Android Studio.

  1. Dans ScoreFragment, dans onCreateView(), ajoutez un écouteur de clics au bouton PlayAgain et appelez viewModel.onPlayAgain().
binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. Exécutez votre application et jouez au jeu. Une fois le jeu terminé, l'écran du score indique le score final et le bouton Play Again (Rejouer). Appuyez sur le bouton PlayAgain (Rejouer), et l'application affiche l'écran du jeu afin que vous puissiez continuer à y jouer.

Bravo ! Vous avez modifié l'architecture de votre application pour utiliser des objets LiveData dans le ViewModel, et vous avez associé des observateurs aux objets LiveData. LiveData informe les objets observateur lorsque la valeur retenue par LiveData change.

Projet Android Studio: GuessTheWord

LiveData

  • LiveData est une classe de conteneur de données observable qui tient compte du cycle de vie, l'un des composants d'architecture Android.
  • Vous pouvez utiliser LiveData pour activer la mise à jour automatique de votre interface utilisateur lorsque les données sont mises à jour.
  • L'objet LiveData est observable, ce qui signifie qu'un observateur comme une activité ou un fragment peut être averti lorsque les données détenues par l'objet LiveData sont modifiées.
  • LiveData contient des données. Il s'agit d'un wrapper qui peut être utilisé avec toutes les données.
  • LiveData tient compte du cycle de vie, c'est-à-dire qu'il ne met à jour que les observateurs qui sont actifs dans leur cycle de vie (STARTED ou RESUMED, par exemple).

Ajouter LiveData

  • Modifiez le type des variables de données dans ViewModel en LiveData ou MutableLiveData.

MutableLiveData est un objet LiveData dont la valeur peut être modifiée. MutableLiveData est une classe générique. Vous devez donc spécifier le type de données qu'elle contient.

  • Pour modifier la valeur des données détenues par le LiveData, utilisez la méthode setValue() sur la variable LiveData.

Pour encapsuler LiveData

  • Vous pouvez modifier le LiveData dans le ViewModel. En dehors de ViewModel, le champ LiveData doit être lisible. Vous pouvez l'implémenter à l'aide d'une propriété de support Kotlin.
  • Une propriété de sauvegarde Kotlin vous permet de renvoyer quelque chose d'un getter autre que l'objet exact.
  • Pour encapsuler la LiveData, utilisez private MutableLiveData dans le ViewModel et renvoyez une propriété de support LiveData en dehors de ViewModel.

Données observables en direct

  • LiveData suit un modèle d'observateur. L'observable est l'objet LiveData, et les observateurs sont les méthodes des contrôleurs de l'interface utilisateur, comme les fragments. Chaque fois que les données encapsulées dans LiveData changent, les méthodes d'observation des contrôleurs de l'interface utilisateur sont alertées.
  • Pour que l'observateur LiveData soit observable, associez un objet observateur à la référence LiveData dans les observateurs (comme les activités et les fragments) à l'aide de la méthode observe().
  • Ce modèle d'observateur LiveData peut être utilisé pour communiquer depuis les ViewModel vers les contrôleurs de l'interface utilisateur.

Cours Udacity:

Documentation pour les développeurs Android:

Autre :

Cette section répertorie les devoirs possibles pour les élèves qui effectuent cet atelier de programmation dans le cadre d'un cours animé par un enseignant. C'est à l'enseignant de procéder comme suit:

  • Si nécessaire, rendez-les.
  • Communiquez aux élèves comment rendre leurs devoirs.
  • Notez les devoirs.

Les enseignants peuvent utiliser ces suggestions autant qu'ils le souhaitent, et ils n'ont pas besoin d'attribuer les devoirs de leur choix.

Si vous suivez vous-même cet atelier de programmation, n'hésitez pas à utiliser ces devoirs pour tester vos connaissances.

Répondez à ces questions.

Question 1

Comment encapsuler le LiveData stocké dans un ViewModel pour que les objets externes puissent lire les données sans pouvoir le mettre à jour ?

  • Dans l'objet ViewModel, indiquez le type de données private LiveData. Utilisez une propriété de support pour exposer les données en lecture seule de type MutableLiveData.
  • Dans l'objet ViewModel, indiquez le type de données private MutableLiveData. Utilisez une propriété de support pour exposer les données en lecture seule de type LiveData.
  • Dans le contrôleur d'interface utilisateur, remplacez le type de données par private MutableLiveData. Utilisez une propriété de support pour exposer les données en lecture seule de type LiveData.
  • Dans l'objet ViewModel, indiquez le type de données LiveData. Utilisez une propriété de support pour exposer les données en lecture seule de type LiveData.

Question 2

LiveData met à jour un contrôleur d'interface utilisateur (un fragment, par exemple) dans un des états suivants ?

  • A repris
  • En arrière-plan
  • En veille
  • Stopped

Question 3

Dans le modèle observateur LiveData, qu'est-ce que l'élément observable (ce qui est observé) ?

  • La méthode d'observation
  • Les données d'un objet LiveData
  • Contrôleur d'interface utilisateur
  • L'objet ViewModel

Démarrez la leçon suivante : 5.3: Liaison de données avec ViewModel et LiveData.

Pour obtenir des liens vers d'autres ateliers de programmation dans ce cours, consultez la page de destination des ateliers de programmation Android Kotlin Fundamentals.