Cet atelier de programmation fait partie du cours Principes de base d'Android en Kotlin. Vous tirerez pleinement parti de ce cours en suivant les ateliers de programmation dans l'ordre. Tous les ateliers de programmation du cours sont listés sur la page de destination des ateliers de programmation Principes de base d'Android en Kotlin.
Introduction
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 changements de configuration de l'appareil. Dans cet atelier de programmation, vous allez apprendre à intégrer LiveData
aux données des classes ViewModel
. LiveData
, qui fait partie 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 change.
Pour utiliser la classe LiveData
, vous configurez des "observateurs" (par exemple, des activités ou des fragments) qui observent les modifications apportées aux données de l'application. LiveData
tient compte du cycle de vie, ce qui signifie qu'il ne met à jour que les observateurs de composants d'application dont l'état du cycle de vie est actif.
Ce que vous devez déjà savoir
- Vous savez comment créer des applications Android de base en langage Kotlin.
- Comment naviguer entre les destinations de votre application.
- Vous comprenez le cycle de vie des activités et des fragments.
- Comment utiliser les objets
ViewModel
dans votre application. - Comment créer des objets
ViewModel
à l'aide de l'interfaceViewModelProvider.Factory
.
Points abordés
- Ce qui rend les objets
LiveData
utiles. - Comment ajouter
LiveData
aux données stockées dans unViewModel
. - Quand et comment utiliser
MutableLiveData
. - Comment ajouter des méthodes d'observation pour voir les modifications effectuées dans
LiveData.
. - Comment encapsuler
LiveData
à l'aide d'une propriété de support. - Comment communiquer entre un contrôleur d'UI et son
ViewModel
correspondant.
Objectifs de l'atelier
- Utilisez
LiveData
pour le mot et le score dans l'application GuessTheWord. - Ajoutez des observateurs qui remarquent quand le mot ou le score changent.
- Mettez à jour les vues de texte qui affichent les valeurs modifiées.
- Utilisez le modèle d'observateur
LiveData
pour ajouter un événement de fin de partie. - Implémentez le bouton Play Again (Rejouer).
Dans les ateliers de programmation de la leçon 5, vous développez l'application GuessTheWord, en commençant par le code de démarrage. GuessTheWord est un jeu de charades à deux joueurs, dans lequel les joueurs collaborent pour obtenir le meilleur score possible.
Le premier joueur regarde les mots dans l'application et mime chacun d'eux à tour de rôle, en veillant à ne pas les montrer au deuxième joueur. Le deuxième joueur essaie de deviner le mot.
Pour jouer, le premier joueur ouvre l'application sur l'appareil et voit un mot, par exemple "guitare", comme indiqué sur la capture d'écran ci-dessous.
Le premier joueur mime le mot, en veillant à ne pas le prononcer.
- Lorsque le deuxième joueur devine le mot, le premier joueur appuie sur le bouton OK, ce qui incrémente le compteur et affiche le mot suivant.
- Si le deuxième joueur ne parvient pas à deviner le mot, le premier joueur appuie sur le bouton Passer, ce qui diminue le nombre de mots d'un et passe au mot suivant.
- Pour mettre fin à la partie, appuyez sur le bouton End Game (Mettre fin à la partie). (Cette fonctionnalité n'est pas incluse dans le code de démarrage du premier atelier de programmation de la série.)
Dans cet atelier de programmation, vous allez améliorer l'application GuessTheWord en ajoutant un événement pour mettre fin à la partie lorsque l'utilisateur a parcouru tous les mots de l'application. Vous allez également ajouter un bouton 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, ou télécharger une application de démarrage.
- (Facultatif) Si vous n'utilisez pas votre code de l'atelier de programmation précédent, téléchargez le code de démarrage pour cet atelier de programmation. Décompressez le code, puis ouvrez le projet dans Android Studio.
- Exécutez l'application et jouez.
- Notez que le bouton Ignorer affiche le mot suivant et diminue le score de un, tandis que le bouton OK affiche le mot suivant et augmente le score de un. Le bouton End Game (Terminer la partie) met fin à la partie.
LiveData
est une classe de conteneur de données observable, sensible au cycle de vie. Par exemple, vous pouvez encapsuler un LiveData
autour du score actuel dans l'application GuessTheWord. Dans cet atelier de programmation, vous découvrirez plusieurs caractéristiques de LiveData
:
LiveData
est une classe observable, ce qui signifie qu'un observateur est averti en cas de modification des données détenues par l'objetLiveData
.LiveData
contient des données ;LiveData
est un wrapper qui peut être utilisé avec n'importe quelle donnée.LiveData
tient compte du cycle de vie, ce qui signifie qu'il ne met à jour que les observateurs dont l'état du cycle de vie est actif, commeSTARTED
ouRESUMED
.
Dans cette tâche, vous allez apprendre à encapsuler n'importe quel type de données dans des objets LiveData
en convertissant les données de score et de mot actuels dans GameViewModel
en LiveData
. Dans une tâche ultérieure, vous ajouterez un observateur à ces objets LiveData
et vous apprendrez à observer LiveData
.
Étape 1 : Modifiez le score et le mot pour utiliser LiveData
- Sous le package
screens/game
, ouvrez le fichierGameViewModel
. - Remplacez le type des variables
score
etword
parMutableLiveData
.MutableLiveData
est unLiveData
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>()
- Dans
GameViewModel
, à l'intérieur du blocinit
, initialisezscore
etword
. Pour modifier la valeur d'une variableLiveData
, vous utilisez la méthodesetValue()
sur la variable. En langage Kotlin, vous pouvez appelersetValue()
à 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
. Dans cette étape, vous modifiez les références à ces variables à l'aide de la propriété value
.
- Dans
GameViewModel
, dans la méthodeonSkip()
, remplacezscore
parscore.value
. Notez l'erreur indiquant quescore
est peut-êtrenull
. Vous corrigerez cette erreur ensuite. - Pour résoudre l'erreur, ajoutez une vérification
null
àscore.value
dansonSkip()
. Appelez ensuite la fonctionminus()
surscore
, qui effectue la soustraction avecnull
-safety.
fun onSkip() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.minus(1)
}
nextWord()
}
- Mettez à jour la méthode
onCorrect()
de la même manière : ajoutez une vérificationnull
à la variablescore
et utilisez la fonctionplus()
.
fun onCorrect() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.plus(1)
}
nextWord()
}
- Dans
GameViewModel
, dans la méthodenextWord()
, remplacez la référenceword
parword
.
value
.
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}
- Dans
GameFragment
, dans la méthodeupdateWordText()
, remplacez la référenceviewModel
.word
parviewModel
.
word
.
value.
.
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}
- Dans
GameFragment
, dans la méthodeupdateScoreText()
, remplacez la référence àviewModel
.score
parviewModel
.
score
.
value.
.
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}
- Dans
GameFragment
, dans la méthodegameFinished()
, remplacez la référence àviewModel
.score
parviewModel
.
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)
}
- Assurez-vous que votre code ne comporte pas d'erreurs. Compilez et exécutez votre application. Elle devrait fonctionner comme avant.
Cette tâche est étroitement liée à la précédente, dans laquelle vous avez converti les données de score et de mots en objets LiveData
. Dans cette tâche, vous allez associer des objets Observer
à ces objets LiveData
.
- Dans
GameFragment,
, à l'intérieur de la méthodeonCreateView()
, associez un objetObserver
à l'objetLiveData
pour le score actuel,viewModel.score
. Utilisez la méthodeobserve()
et placez le code après l'initialisation deviewModel
. Utilisez une expression lambda pour simplifier le code. (Une expression lambda est une fonction anonyme non déclarée, mais 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 Mac), puis importez androidx.lifecycle.Observer
.
- L'observateur que vous venez de créer reçoit un événement lorsque les données détenues par l'objet
LiveData
observé changent. Dans l'observateur, mettez à jour le scoreTextView
avec le nouveau score.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
- Associez un objet
Observer
à l'objetLiveData
du mot actuel. Procédez de la même manière que pour associer un objetObserver
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, le score
ou le word
affiché à l'écran est désormais mis à jour automatiquement.
- Dans
GameFragment
, supprimez les méthodesupdateWordText()
etupdateScoreText()
, ainsi que toutes les références s'y rapportant. Vous n'en avez plus besoin, car les vues de texte sont mises à jour par les méthodes d'observateurLiveData
. - Exécutez votre application. Votre jeu devrait fonctionner exactement comme auparavant, mais il utilise désormais les observateurs
LiveData
etLiveData
.
L'encapsulation permet de restreindre l'accès direct à certains champs d'un objet. 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, n'importe quelle classe externe peut modifier les variables score
et word
à l'aide de la propriété value
, par exemple en utilisant viewModel.score.value
. Cela n'a peut-être pas d'importance dans l'application que vous développez dans cet atelier de programmation, mais dans une application de production, vous souhaitez contrôler les données des objets ViewModel
.
Seul le ViewModel
doit modifier les données de votre application. Toutefois, les contrôleurs d'UI doivent lire les données. Les champs de données ne peuvent donc pas être entièrement privés. Pour encapsuler les données de votre application, vous utilisez les objets MutableLiveData
et LiveData
.
MutableLiveData
contre LiveData
:
- Comme son nom l'indique, les données d'un objet
MutableLiveData
peuvent être modifiées. Dans leViewModel
, les données doivent être modifiables. Elles utilisent doncMutableLiveData
. - Les données d'un objet
LiveData
peuvent être lues, mais pas modifiées. En dehors deViewModel
, les données doivent être lisibles, mais pas modifiables. Elles doivent donc être présentées commeLiveData
.
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 d'un getter qui n'est pas l'objet exact. Dans cette tâche, vous allez implémenter une propriété de sauvegarde pour les objets score
et word
dans l'application GuessTheWord.
Ajouter une propriété de support au score et au mot
- Dans
GameViewModel
, définissez l'objetscore
actuel surprivate
. - 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 du jeu, à utiliser en interne. - Créez une version publique du type
LiveData
, appeléescore
.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
- Une erreur d'initialisation s'affiche. Cette erreur se produit, car dans
GameFragment
,score
est une référenceLiveData
etscore
ne peut plus accéder à son setter. Pour en savoir plus sur les getters et les setters en Kotlin, consultez Getters et setters.
Pour résoudre l'erreur, remplacez la méthodeget()
pour l'objetscore
dansGameViewModel
et renvoyez la propriété de sauvegarde,_score
.
val score: LiveData<Int>
get() = _score
- Dans
GameViewModel
, remplacez les références descore
par sa version interne modifiable,_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)
}
...
}
- Renommez l'objet
word
en_word
et ajoutez-lui une propriété de support, comme vous l'avez fait pour l'objetscore
.
// 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)
}
}
Bravo, vous avez encapsulé les objets LiveData
word
et score
.
Votre application actuelle accède à l'écran du score lorsque l'utilisateur appuie sur le bouton End Game (Fin de partie). Vous souhaitez également que l'application accède à l'écran des scores lorsque les joueurs ont parcouru tous les mots. Une fois que les joueurs ont terminé avec le dernier mot, vous voulez que le jeu se termine automatiquement afin que l'utilisateur n'ait pas à appuyer sur le bouton.
Pour implémenter cette fonctionnalité, vous avez besoin qu'un événement soit déclenché et communiqué au fragment à partir de 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 de fin de partie.
Le modèle d'observateur
Le modèle d'observateur est un modèle de conception logicielle. Il spécifie la communication entre les objets : un observable (le "sujet" de l'observation) et les observateurs. Un observable est un objet qui informe les observateurs des changements d'état.
Dans le cas de LiveData
dans cette application, l'observable (sujet) est l'objet LiveData
, et les observateurs sont les méthodes des contrôleurs d'UI, tels que les fragments. Un changement d'état se produit chaque fois que les données encapsulées dans LiveData
changent. Les classes LiveData
sont essentielles pour communiquer du ViewModel
au fragment.
Étape 1 : Utilisez LiveData pour détecter un événement de fin de partie
Dans cette tâche, vous allez utiliser le modèle d'observateur LiveData
pour modéliser un événement de fin de partie.
- Dans
GameViewModel
, créez un objetMutableLiveData
Boolean
appelé_eventGameFinish
. Cet objet contiendra l'événement de fin de partie. - Après avoir initialisé l'objet
_eventGameFinish
, créez et initialisez une propriété de sauvegarde appeléeeventGameFinish
.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinish
- Dans
GameViewModel
, ajoutez une méthodeonGameFinish()
. Dans la méthode, définissez l'événement de fin de partie,eventGameFinish
, surtrue
.
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}
- Dans
GameViewModel
, à l'intérieur de la méthodenextWord()
, 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)
}
}
- Dans
GameFragment
, à l'intérieur deonCreateView()
, après avoir initialiséviewModel
, associez un observateur àeventGameFinish
. Utilisez la méthodeobserve()
. Dans la fonction lambda, appelez la méthodegameFinished()
.
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
if (hasFinished) gameFinished()
})
- Exécutez votre application, jouez et parcourez tous les mots. L'application accède automatiquement à l'écran du score au lieu de rester dans le fragment de jeu jusqu'à ce que vous appuyiez sur Fin de partie.
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. - Le code que vous avez ajouté a introduit un problème de cycle de vie. Pour comprendre le problème, dans la classe
GameFragment
, mettez en commentaire le code de navigation dans la méthodegameFinished()
. Veillez à conserver le messageToast
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)
}
- Exécutez votre application, jouez et parcourez tous les mots. Un toast indiquant "La partie vient de se terminer" s'affiche brièvement en bas de l'écran de jeu, ce qui est le comportement attendu.
Faites maintenant pivoter l'appareil ou l'émulateur. Le toast s'affiche à nouveau ! Faites pivoter l'appareil plusieurs fois de plus. Vous devriez voir le message à chaque fois. Il s'agit d'un bug, car le toast ne devrait s'afficher qu'une seule fois, à la fin de la partie. Le toast ne doit pas s'afficher chaque fois que le fragment est recréé. Vous résoudrez ce problème dans la prochaine tâche.
Étape 2 : Réinitialisez l'événement "game-finished"
En général, LiveData
ne transmet des mises à jour aux observateurs que si les données sont modifiées. Il existe 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 de fin de partie est déclenché à plusieurs reprises 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 à nouveau déclenchée et le toast s'affiche.
Dans cette tâche, vous allez résoudre ce problème et n'afficher le toast qu'une seule fois en réinitialisant l'indicateur eventGameFinish
dans GameViewModel
.
- Dans
GameViewModel
, ajoutez une méthodeonGameFinishComplete()
pour réinitialiser l'événement de fin de partie,_eventGameFinish
.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}
- Dans
GameFragment
, à la fin degameFinished()
, appelezonGameFinishComplete()
sur l'objetviewModel
. (Pour l'instant, laissez le code de navigation en commentaire dansgameFinished()
.)
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}
- Exécutez l'application et jouez. Parcourez tous les mots, puis modifiez l'orientation de l'écran de l'appareil. Le toast ne s'affiche qu'une seule fois.
- Dans
GameFragment
, à l'intérieur de la méthodegameFinished()
, supprimez la mise en commentaire du code de navigation.
Pour supprimer la mise en commentaire dans Android Studio, sélectionnez les lignes commentées et appuyez surControl+/
(Command+/
sur 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()
}
Importez androidx.navigation.fragment.NavHostFragment.findNavController
, si Android Studio vous le demande.
- Exécutez l'application et jouez. Assurez-vous que l'application accède automatiquement à l'écran du score final après que vous avez parcouru tous les mots.
Bien joué ! Votre application utilise LiveData
pour déclencher un événement de fin de partie afin de communiquer du GameViewModel
au fragment de jeu que la liste de mots est vide. Le fragment de jeu accède ensuite au fragment de score.
Dans cette tâche, vous allez remplacer le score par un objet LiveData
dans ScoreViewModel
et y associer un observateur. Cette tâche est semblable à celle que vous avez effectuée lorsque vous avez ajouté LiveData
à GameViewModel
.
Vous apportez ces modifications à ScoreViewModel
pour que toutes les données de votre application utilisent LiveData
.
- Dans
ScoreViewModel
, remplacez le type de la variablescore
parMutableLiveData
. Renommez-le par convention en_score
et ajoutez une propriété de support.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
- Dans
ScoreViewModel
, à l'intérieur du blocinit
, initialisez_score
. Vous pouvez supprimer ou laisser le journal dans le blocinit
comme vous le souhaitez.
init {
_score.value = finalScore
}
- Dans
ScoreFragment
, à l'intérieur deonCreateView()
, après avoir initialiséviewModel
, associez un observateur à l'objetLiveData
du score. Dans l'expression lambda, définissez la valeur du score sur l'affichage de texte du score. Supprimez le code qui attribue directement la valeur du score à la vue de texte à partir deViewModel
.
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()
Lorsqu'Android Studio vous le demande, importez androidx.lifecycle.Observer
.
- Exécutez votre application et jouez. L'application devrait fonctionner comme avant, mais elle utilise désormais
LiveData
et un observateur pour mettre à jour le score.
Dans cette tâche, vous allez ajouter un bouton Rejouer à l'écran du score et implémenter son écouteur de clics à l'aide d'un événement LiveData
. Le bouton déclenche un événement permettant de passer de l'écran de score à l'écran de jeu.
Le code de démarrage de l'application inclut le bouton Rejouer, mais il est masqué.
- Dans
res/layout/score_fragment.xml
, pour le boutonplay_again_button
, remplacez la valeur de l'attributvisibility
parvisible
.
<Button
android:id="@+id/play_again_button"
...
android:visibility="visible"
/>
- Dans
ScoreViewModel
, ajoutez un objetLiveData
pour contenir unBoolean
appelé_eventPlayAgain
. Cet objet permet d'enregistrer l'événementLiveData
pour passer de l'écran du score à l'écran du jeu.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgain
- Dans
ScoreViewModel
, définissez des méthodes pour définir et réinitialiser l'événement,_eventPlayAgain
.
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}
- Dans
ScoreFragment
, ajoutez un observateur poureventPlayAgain
. Placez le code à la fin deonCreateView()
, avant l'instructionreturn
. Dans l'expression lambda, revenez à l'écran du jeu et réinitialisezeventPlayAgain
.
// 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
lorsqu'Android Studio vous le demande.
- Dans
ScoreFragment
, à l'intérieur deonCreateView()
, ajoutez un écouteur de clics au bouton PlayAgain (Rejouer) et appelezviewModel
.onPlayAgain()
.
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }
- Exécutez votre application et jouez. Une fois la partie terminée, l'écran du score affiche le score final et le bouton Rejouer. Appuyez sur le bouton PlayAgain (Rejouer). L'application vous redirige vers l'écran du jeu pour que vous puissiez rejouer.
Bravo ! Vous avez modifié l'architecture de votre application pour utiliser des objets LiveData
dans ViewModel
et vous avez associé des observateurs aux objets LiveData
. LiveData
avertit les objets observateurs lorsque la valeur détenue par LiveData
change.
Projet Android Studio : GuessTheWord
LiveData
LiveData
est une classe de conteneur de données observable, sensible au cycle de vie, qui fait partie des composants d'architecture Android.- Vous pouvez utiliser
LiveData
pour permettre à votre UI de se mettre à jour automatiquement lorsque les données sont modifiées. LiveData
est une classe observable, ce qui signifie qu'un observateur tel qu'une activité ou un fragment peut être averti en cas de modification des données détenues par l'objetLiveData
.LiveData
contient des données ; il s'agit d'un wrapper qui peut être utilisé avec n'importe quelle donnée.LiveData
tient compte du cycle de vie, ce qui signifie qu'il ne met à jour que les observateurs dont l'état du cycle de vie est actif, commeSTARTED
ouRESUMED
.
Pour ajouter LiveData
- Remplacez le type des variables de données dans
ViewModel
parLiveData
ouMutableLiveData
.
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
LiveData
, utilisez la méthodesetValue()
sur la variableLiveData
.
Pour encapsuler LiveData
- Le
LiveData
à l'intérieur duViewModel
doit être modifiable. En dehors deViewModel
,LiveData
doit être lisible. Pour ce faire, vous pouvez utiliser une propriété de support Kotlin. - Une propriété de support Kotlin vous permet de renvoyer un élément d'un getter qui n'est pas l'objet exact.
- Pour encapsuler le
LiveData
, utilisezprivate
MutableLiveData
à l'intérieur duViewModel
et renvoyez une propriété de sauvegardeLiveData
en dehors duViewModel
.
Observable LiveData
LiveData
suit un modèle d'observateur. L'"observable" est l'objetLiveData
, et les observateurs sont les méthodes des contrôleurs d'UI, comme les fragments. Chaque fois que les données encapsulées dansLiveData
changent, les méthodes d'observation des contrôleurs d'UI sont averties.- Pour rendre
LiveData
observable, associez un objet observateur à la référenceLiveData
dans les observateurs (tels que les activités et les fragments) à l'aide de la méthodeobserve()
. - Ce modèle d'observateur
LiveData
peut être utilisé pour communiquer depuisViewModel
vers les contrôleurs d'UI.
Cours Udacity :
Documentation pour les développeurs Android :
- Présentation de ViewModel
- Présentation de LiveData
MutableLiveData
- Guide de l'architecture des applications
Autre :
- Propriété de sauvegarde en Kotlin
Cette section répertorie les devoirs possibles pour les élèves qui suivent cet atelier de programmation dans le cadre d'un cours animé par un enseignant. Il revient à l'enseignant d'effectuer les opérations suivantes :
- Attribuer des devoirs si nécessaire
- Indiquer aux élèves comment rendre leurs devoirs
- Noter les devoirs
Les enseignants peuvent utiliser ces suggestions autant qu'ils le souhaitent, et ne doivent pas hésiter à attribuer d'autres devoirs aux élèves s'ils le jugent nécessaire.
Si vous suivez cet atelier de programmation par vous-même, n'hésitez pas à utiliser ces devoirs pour tester vos connaissances.
Répondre aux questions suivantes
Question 1
Comment encapsuler le LiveData
stocké dans un ViewModel
pour que les objets externes puissent lire les données sans pouvoir les mettre à jour ?
- Dans l'objet
ViewModel
, remplacez le type de données parprivate
LiveData
. Utilisez une propriété de support pour exposer des données en lecture seule du typeMutableLiveData
. - Dans l'objet
ViewModel
, remplacez le type de données parprivate
MutableLiveData
. Utilisez une propriété de support pour exposer des données en lecture seule du typeLiveData
. - Dans le contrôleur d'interface utilisateur, remplacez le type de données par
private
MutableLiveData
. Utilisez une propriété de support pour exposer des données en lecture seule du typeLiveData
. - Dans l'objet
ViewModel
, remplacez le type de données parLiveData
. Utilisez une propriété de support pour exposer des données en lecture seule du typeLiveData
.
Question 2
Parmi les états suivants, lequel permet à LiveData
de mettre à jour un contrôleur d'interface utilisateur (un fragment, par exemple) ?
- A repris
- En arrière-plan
- Suspendue
- Arrêté
Question 3
Dans le modèle d'observateur LiveData
, quel est l'élément observable (ce qui est observé) ?
- La méthode de l'observateur
- Les données d'un objet
LiveData
- Le contrôleur d'interface utilisateur
- L'objet
ViewModel
Passez à la leçon suivante :
Pour obtenir des liens vers d'autres ateliers de programmation de ce cours, consultez la page de destination des ateliers de programmation Principes de base d'Android en Kotlin.