Conceitos básicos do Kotlin para Android 05.2: observadores de LiveData e LiveData

Este codelab faz parte do curso Conceitos básicos do Kotlin para Android. Você aproveitará mais o curso se fizer os codelabs em sequência. Todos os codelabs do curso estão listados na página de destino dos codelabs do curso Conceitos básicos do Kotlin para Android.

Introdução

No codelab anterior, você usou uma ViewModel no app GuessTheWord para permitir que os dados do app sobrevivam às mudanças de configuração do dispositivo. Neste codelab, você aprenderá a integrar o LiveData com os dados das classes ViewModel. O LiveData, que é um dos Componentes da arquitetura do Android, permite criar objetos de dados que notificam as visualizações quando o banco de dados subjacente é modificado.

Para usar a classe LiveData, configure "observadores" (por exemplo, atividades ou fragmentos) que observam alterações nos dados do aplicativo. O LiveData é compatível com o ciclo de vida, então atualiza apenas os observadores do componente do app que estão em um estado ativo no ciclo de vida.

O que você já precisa saber

  • Saber criar apps Android básicos em Kotlin.
  • Como navegar entre os destinos do app.
  • Ciclo de vida de atividades e fragmentos.
  • Como usar objetos ViewModel no seu app.
  • Como criar objetos ViewModel usando a interface ViewModelProvider.Factory.

O que você vai aprender

  • O que torna objetos LiveData úteis.
  • Como adicionar um LiveData aos dados armazenados em um ViewModel.
  • Quando e como usar o MutableLiveData
  • Como adicionar métodos do observador para observar mudanças no LiveData.
  • Como encapsular LiveData usando uma propriedade de apoio.
  • Como se comunicar entre um controlador de IU e o ViewModel correspondente.

Atividades do laboratório

  • Use LiveData para a palavra e a pontuação no aplicativo GuessTheWord.
  • Adicione observadores que percebem quando a palavra ou a pontuação muda.
  • Atualize as visualizações de texto que exibem valores alterados.
  • Use o padrão de observador LiveData para adicionar um evento de jogo concluído.
  • Implemente o botão Jogar novamente.

Nos codelabs da Lição 5, você desenvolve o app GuessTheWord, começando com o código inicial. O GuessTheWord é um jogo de dois jogadores no estilo de charadas em que os jogadores colaboram para conseguir a maior pontuação possível.

O primeiro jogador analisa as palavras no app e age uma por vez, garantindo que a palavra não seja exibida ao segundo jogador. O segundo participante tenta adivinhar a palavra.

Para jogar, o primeiro jogador abre o app no dispositivo e vê uma palavra, por exemplo, "quot;guitar"" como mostrado na captura de tela abaixo.

O primeiro jogador age com a palavra, tendo cuidado para não dizer a palavra em si.

  • Quando o segundo jogador adivinhar a palavra corretamente, o primeiro pressione o botão Got It. Isso aumenta a contagem em um e exibe a próxima palavra.
  • Se o segundo jogador não conseguir adivinhar a palavra, o primeiro jogador pressionará o botão Skip, que diminui a contagem em um e pula para a próxima.
  • Para encerrar o jogo, pressione o botão Encerrar jogo. Essa funcionalidade não está no código inicial do primeiro codelab da série.

Neste codelab, você vai melhorar o app GuessTheWord adicionando um evento para encerrar o jogo quando o usuário passar por todas as palavras dele. Você também adicionará um botão Jogar novamente no fragmento de pontuação para que o usuário possa jogar de novo.

Créditos

Tela de jogo

Tela de pontuação

Nesta tarefa, você localizará e executará o código inicial para este codelab. Você pode usar o app GuessTheWord que criou no codelab anterior como seu código inicial ou fazer o download de um app inicial.

  1. (Opcional) Se você não está usando seu código do codelab anterior, faça o download do código inicial deste codelab. Descompacte o código e abra o projeto no Android Studio.
  2. Execute o app e jogue.
  3. O botão Pular exibe a próxima palavra e diminui a pontuação em um, e o botão Ok mostra a próxima palavra e aumenta a pontuação em um. O botão Encerrar jogo encerra o jogo.

LiveData é uma classe armazenadora de dados observáveis compatível com o ciclo de vida. Por exemplo, você pode unir uma LiveData à pontuação atual no app GuessTheWord. Neste codelab, você aprenderá sobre várias características de LiveData:

  • O LiveData é observável, o que significa que um observador é notificado quando os dados contidos no objeto LiveData mudam.
  • O LiveData armazena dados. LiveData é um wrapper que pode ser usado com qualquer tipo de dados.
  • O LiveData é compatível com o ciclo de vida, o que significa que ele só atualiza os observadores que estão em um estado de ciclo de vida ativo, como STARTED ou RESUMED.

Nesta tarefa, você aprenderá a unir qualquer tipo de dados em objetos LiveData convertendo a pontuação e os dados de palavras atuais no GameViewModel em LiveData. Em uma tarefa posterior, você adicionará um observador a esses objetos LiveData e aprenderá a observar o LiveData.

Etapa 1: alterar a pontuação e a palavra para usar o LiveData

  1. No pacote screens/game, abra o arquivo GameViewModel.
  2. Mude o tipo das variáveis score e word para MutableLiveData.

    MutableLiveData é um LiveData cujo valor pode ser alterado. A MutableLiveData é uma classe genérica, então você precisa especificar o tipo de dados dela.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
  1. No GameViewModel, dentro do bloco init, inicialize score e word. Para mudar o valor de uma variável LiveData, use o método setValue() nela. No Kotlin, você pode chamar setValue() usando a propriedade value.
init {

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

Etapa 2: atualizar a referência do objeto LiveData

As variáveis score e word agora são do tipo LiveData. Nesta etapa, você mudará as referências para essas variáveis usando a propriedade value.

  1. Em GameViewModel, no método onSkip(), mude score para score.value. O erro sobre score pode ser null. O erro será corrigido a seguir.
  2. Para resolver o erro, adicione uma verificação null a score.value em onSkip(). Em seguida, chame a função minus() no score, que executa a subtração com a segurança null.
fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}
  1. Atualize o método onCorrect() da mesma forma: adicione uma verificação null à variável score e use a função plus().
fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}
  1. No GameViewModel, no método nextWord(), mude a referência word para word.value.
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}
  1. No GameFragment, no método updateWordText(), mude a referência para viewModel.word para viewModel.word.value.
/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}
  1. No GameFragment, no método updateScoreText(), mude a referência para viewModel.score para viewModel.score.value.
private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}
  1. No GameFragment, no método gameFinished(), mude a referência para viewModel.score para viewModel.score.value. Adicione a confirmação de segurança null.
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. Verifique se não há erros no seu código. Compile e execute seu aplicativo. A funcionalidade do aplicativo deve ser a mesma de antes.

Essa tarefa está estreitamente relacionada à tarefa anterior, em que você converteu a pontuação e os dados das palavras em objetos LiveData. Nesta tarefa, você anexará objetos Observer a esses objetos LiveData.

  1. No GameFragment, no método onCreateView(), anexe um objeto Observer ao objeto LiveData para a pontuação atual, viewModel.score. Use o método observe() e coloque o código após a inicialização do viewModel. Use uma expressão lambda para simplificar o código. Uma expressão lambda é uma função anônima que não é declarada, mas é transmitida imediatamente como uma expressão.
viewModel.score.observe(this, Observer { newScore ->
})

Resolva a referência a Observer. Para fazer isso, clique em Observer, pressione Alt+Enter (Option+Enter em um Mac) e importe androidx.lifecycle.Observer.

  1. O observador que você acabou de criar recebe um evento quando os dados retidos pelo objeto LiveData observado mudam. No observador, atualize a pontuação TextView com a nova pontuação.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. Anexe um objeto Observer ao objeto atual da palavra LiveData. Faça isso da mesma forma que você anexou um objeto Observer à pontuação atual.
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})

Quando o valor de score ou word mudar, o score ou word exibido na tela será atualizado automaticamente.

  1. No GameFragment, exclua os métodos updateWordText() e updateScoreText() e todas as referências a eles. Eles não são mais necessários porque as visualizações de texto são atualizadas pelos métodos de observação do LiveData.
  2. Execute o app. Seu app de jogo funcionará exatamente como antes, mas agora usa os observadores LiveData e LiveData.

O encapsulamento é uma maneira de restringir o acesso direto a alguns dos campos de um objeto. Ao encapsular um objeto, você expõe um conjunto de métodos públicos que modificam os campos internos particulares. Usando o encapsulamento, você controla como outras classes manipulam os campos internos.

No código atual, qualquer classe externa pode modificar as variáveis score e word com a propriedade value. Por exemplo, usando viewModel.score.value. Talvez não importa no app que você está desenvolvendo neste codelab, mas em um app de produção, você quer controle sobre os dados nos objetos ViewModel.

Somente o ViewModel precisa editar os dados no seu app. No entanto, os controladores de IU precisam ler os dados, portanto, os campos de dados não podem ser totalmente particulares. Para encapsular os dados do app, use os objetos MutableLiveData e LiveData.

MutableLiveData x LiveData:

  • Os dados em um objeto MutableLiveData podem ser alterados, como o nome indica. No ViewModel, os dados precisam ser editáveis. Portanto, ele usa MutableLiveData.
  • Os dados em um objeto LiveData podem ser lidos, mas não alterados. Fora do ViewModel, os dados precisam ser legíveis, mas não editáveis, portanto, os dados precisam ser expostos como LiveData.

Para implementar essa estratégia, você usa uma propriedade de apoio do Kotlin (link em inglês). Uma propriedade de apoio permite que você retorne algo de um getter diferente do objeto exato. Nesta tarefa, você vai implementar uma propriedade de apoio para os objetos score e word no app GuessTheWord.

Adicione uma propriedade de apoio para pontuação e palavra

  1. Em GameViewModel, torne o objeto score atual private.
  2. Para seguir a convenção de nomenclatura usada nas propriedades de apoio, mude score para _score. A propriedade _score agora é a versão mutável da pontuação do jogo, que será usada internamente.
  3. Crie uma versão pública do tipo LiveData, chamada score.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
  1. Você verá um erro de inicialização. Esse erro ocorre porque, dentro do GameFragment, o score é uma referência LiveData, e o score não pode mais acessar o setter. Para saber mais sobre getters e setters no Kotlin, consulte Getters e setters.

    Para resolver o erro, modifique o método get() do objeto score em GameViewModel e retorne a propriedade de apoio _score.
val score: LiveData<Int>
   get() = _score
  1. No GameViewModel, mude as referências de score para a versão mutável interna, _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. Renomeie o objeto word como _word e adicione uma propriedade de apoio, como você fez para o objeto 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)
   }
}

Muito bem! Você encapsulau os objetos LiveData e score de word.

O app atual navega para a tela de pontuação quando o usuário toca no botão Encerrar jogo. Você também quer que o app navegue até a tela de pontuação quando os jogadores passarem por todas as palavras. Depois que os jogadores terminam com a última palavra, o jogo precisa terminar automaticamente para que o usuário não precise tocar no botão.

Para implementar essa funcionalidade, você precisa que um evento seja acionado e comunicado ao fragmento da ViewModel quando todas as palavras forem exibidas. Para fazer isso, use o padrão de observador LiveData para modelar um evento concluído no jogo.

O padrão do observador

O padrão do observador é um padrão de design de software. Ele especifica a comunicação entre os objetos: um observável (o "objetivo" e os observadores). Um elemento observável é um objeto que notifica os observadores sobre as mudanças no estado dele.

No caso do LiveData neste app, o observável (assunto) é o objeto LiveData, e os observadores são os métodos nos controladores da IU, como fragmentos. Uma mudança de estado acontece sempre que os dados agrupados no LiveData mudam. As classes LiveData são essenciais para a comunicação do ViewModel com o fragmento.

Etapa 1: usar o LiveData para detectar um evento concluído no jogo

Nesta tarefa, você usará o padrão de observador LiveData para modelar um evento concluído no jogo.

  1. No GameViewModel, crie um objeto Boolean MutableLiveData chamado _eventGameFinish. Esse objeto conterá o evento finalizado do jogo.
  2. Depois de inicializar o objeto _eventGameFinish, crie e inicialize uma propriedade de apoio chamada eventGameFinish.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
   get() = _eventGameFinish
  1. No GameViewModel, adicione um método onGameFinish(). No método, defina o evento finalizado do jogo, eventGameFinish, como true.
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. No GameViewModel, no método nextWord(), encerre o jogo se a lista de palavras estiver vazia.
private fun nextWord() {
   if (wordList.isEmpty()) {
       onGameFinish()
   } else {
       //Select and remove a _word from the list
       _word.value = wordList.removeAt(0)
   }
}
  1. No GameFragment, no método onCreateView(), depois de inicializar o viewModel, anexe um observador ao eventGameFinish. Use o método observe(). Dentro da função lambda, chame o método gameFinished().
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
   if (hasFinished) gameFinished()
})
  1. Execute o app, jogue e leia todas as palavras. O app navegará para a tela de pontuação automaticamente, em vez de permanecer no fragmento do jogo até você tocar em Encerrar jogo.

    Depois que a lista de palavras está vazia, o eventGameFinish é definido, o método de observador associado no fragmento do jogo é chamado, e o app navega para o fragmento de tela.
  2. O código adicionado introduziu um problema de ciclo de vida. Para entender o problema, na classe GameFragment, deixe um comentário no código de navegação no método gameFinished(). Mantenha a mensagem Toast no método.
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. Execute o app, jogue e leia todas as palavras. A mensagem de aviso "O jogo acabou" aparece na parte inferior da tela do jogo, que é o comportamento esperado.

Agora, gire o dispositivo ou emulador. A mensagem de aviso será exibida novamente. Gire o dispositivo mais algumas vezes e você provavelmente verá a mensagem de aviso. Isso é um bug, porque o aviso será exibido apenas uma vez, quando o jogo terminar. O aviso não será exibido sempre que o fragmento for recriado. Você resolverá esse problema na próxima tarefa.

Etapa 2: redefinir o evento do jogo concluído

Geralmente, o LiveData exibe atualizações para os observadores apenas quando os dados mudam. Uma exceção a esse comportamento é que os observadores também recebem atualizações quando o observador muda de um estado inativo para um ativo.

É por isso que o aviso concluído do jogo é acionado repetidamente no app. Quando o fragmento de jogo é recriado depois da rotação da tela, ele sai de um estado inativo para um ativo. O observador no fragmento é reconectado ao ViewModel existente e recebe os dados atuais. O método gameFinished() será acionado novamente, e a notificação toast será exibida.

Nesta tarefa, você vai corrigir esse problema e exibir o aviso apenas uma vez, redefinindo a sinalização eventGameFinish no GameViewModel.

  1. No GameViewModel, adicione um método onGameFinishComplete() para redefinir o evento concluído do jogo, _eventGameFinish.
/** Method for the game completed event **/

fun onGameFinishComplete() {
   _eventGameFinish.value = false
}
  1. No GameFragment ao final de gameFinished(), chame onGameFinishComplete() no objeto viewModel. Deixe o código de navegação em gameFinished() comentado por enquanto.
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. Execute o app e jogue. Leia todas as palavras e mude a orientação da tela do dispositivo. A notificação toast é exibida apenas uma vez.
  2. No GameFragment, no método gameFinished(), remova a marca de comentário do código de navegação.

    Para remover a marca de comentário no Android Studio, selecione as linhas comentadas e pressione Control+/ (Command+/ no 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()
}

Se solicitado pelo Android Studio, importe androidx.navigation.fragment.NavHostFragment.findNavController.

  1. Execute o app e jogue. Verifique se o aplicativo navega automaticamente para a tela da pontuação final depois de passar por todas as palavras.

Muito bem! O app usa a LiveData para acionar um evento de jogo concluído para comunicar ao GameViewModel ao fragmento do jogo que a lista de palavras está vazia. O fragmento do jogo navegará para o fragmento de pontuação.

Nesta tarefa, você vai mudar a pontuação para um objeto LiveData no ScoreViewModel e anexar um observador a ele. Essa tarefa é semelhante ao que você fez quando adicionou LiveData à GameViewModel.

Faça essas mudanças no ScoreViewModel para que todos os dados do app usem LiveData.

  1. No ScoreViewModel, mude o tipo da variável score para MutableLiveData. Renomeie-o por _score e adicione uma propriedade de apoio.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
   get() = _score
  1. No ScoreViewModel, dentro do bloco init, inicialize o _score. Você pode remover ou deixar o registro no bloco init como quiser.
init {
   _score.value = finalScore
}
  1. No ScoreFragment, no método onCreateView(), depois de inicializar o viewModel, anexe um observador para o objeto de pontuação LiveData. Na expressão lambda, defina o valor da pontuação como a visualização de texto da pontuação. Remova o código que atribui diretamente a visualização de texto com o valor da pontuação da ViewModel.

Código a ser adicionado:

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

Código a ser removido:

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

Quando solicitado pelo Android Studio, importe androidx.lifecycle.Observer.

  1. Execute o app e jogue. O app funcionará como antes, mas agora usa LiveData e um observador para atualizar a pontuação.

Nesta tarefa, você adicionará o botão Jogar novamente à tela de pontuação e implementará o listener de clique usando um evento LiveData. O botão aciona um evento para navegar da tela de pontuação para a tela do jogo.

O código inicial do app inclui o botão Jogar novamente, mas ele está oculto.

  1. Em res/layout/score_fragment.xml, para o botão play_again_button, altere o valor do atributo visibility para visible.
<Button
   android:id="@+id/play_again_button"
...
   android:visibility="visible"
 />
  1. No ScoreViewModel, adicione um objeto LiveData para armazenar um Boolean chamado _eventPlayAgain. Esse objeto é usado para salvar o evento LiveData para navegar da tela de pontuação para a tela do jogo.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. Em ScoreViewModel, defina métodos para definir e redefinir o evento, _eventPlayAgain.
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. No ScoreFragment, adicione um observador para o eventPlayAgain. Coloque o código no final de onCreateView(), antes da instrução return. Na expressão lambda, navegue de volta para a tela do jogo e redefina o eventPlayAgain.
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
   if (playAgain) {
      findNavController().navigate(ScoreFragmentDirections.actionRestart())
       viewModel.onPlayAgainComplete()
   }
})

Importe androidx.navigation.fragment.findNavController quando solicitado pelo Android Studio.

  1. No ScoreFragment, no método onCreateView(), adicione um listener de clique ao botão PlayAgain e chame viewModel.onPlayAgain().
binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. Execute o app e jogue. Quando o jogo terminar, a tela da pontuação mostrará a pontuação final e o botão Jogar novamente. Toque no botão PlayAgain e o app navegará até a tela do jogo para você jogar novamente.

Bom trabalho! Você mudou a arquitetura do seu app para usar objetos LiveData no ViewModel e anexou observadores aos objetos LiveData. O LiveData notifica os objetos de observação quando o valor mantido pela LiveData muda.

Projeto do Android Studio: GuessTheWord

LiveData

  • A LiveData é uma classe armazenadora de dados observáveis que reconhece o ciclo de vida, um dos Componentes da arquitetura do Android.
  • Use o LiveData para ativar a atualização automática da IU quando os dados forem atualizados.
  • O LiveData é observável, o que significa que um observador, como uma atividade ou um fragmento, pode ser notificado quando os dados retidos pelo objeto LiveData mudam.
  • O LiveData armazena dados. Ele é um wrapper que pode ser usado com qualquer tipo de dados.
  • O LiveData é compatível com o ciclo de vida, o que significa que ele só atualiza os observadores que estão em um estado de ciclo de vida ativo, como STARTED ou RESUMED.

Adicionar o LiveData

  • Mude o tipo das variáveis de dados na ViewModel para LiveData ou MutableLiveData.

MutableLiveData é um objeto LiveData cujo valor pode ser alterado. A MutableLiveData é uma classe genérica, então você precisa especificar o tipo de dados dela.

  • Para mudar o valor dos dados retidos por LiveData, use o método setValue() na variável LiveData.

Para encapsular o LiveData

  • O LiveData no ViewModel precisa ser editável. Fora do ViewModel, o LiveData precisa ser legível. Isso pode ser implementado usando uma propriedade de backup do Kotlin.
  • Uma propriedade de apoio do Kotlin permite retornar algo de um getter diferente do objeto exato.
  • Para encapsular a LiveData, use private MutableLiveData dentro da ViewModel e retorne uma propriedade de apoio LiveData fora da ViewModel.

LiveData observável

  • LiveData segue um padrão de observador. O "observable" é o objeto LiveData, e os observadores são os métodos nos controladores de IU, como fragmentos. Sempre que os dados agrupados no LiveData mudarem, os métodos do observador nos controladores de IU serão notificados.
  • Para tornar o LiveData observável, anexe um objeto observador à referência LiveData nos observadores (como atividades e fragmentos) usando o método observe().
  • Esse padrão de observador LiveData pode ser usado para comunicação entre os ViewModel e os controladores de IU.

Curso da Udacity:

Documentação do desenvolvedor Android:

Outro:

Esta seção lista as possíveis atividades para os alunos que estão trabalhando neste codelab como parte de um curso ministrado por um instrutor. Cabe ao instrutor fazer o seguinte:

  • Se necessário, atribua o dever de casa.
  • Informe aos alunos como enviar o dever de casa.
  • Atribua nota aos trabalhos de casa.

Os professores podem usar essas sugestões o quanto quiserem, e eles devem se sentir à vontade para passar o dever de casa como achar adequado.

Se você estiver fazendo este codelab por conta própria, use essas atividades para testar seu conhecimento.

Responda a estas perguntas

Pergunta 1

Como encapsular o LiveData armazenado em um ViewModel para que objetos externos possam ler dados sem atualizá-los?

  • No objeto ViewModel, mude o tipo dos dados para private LiveData. Use uma propriedade de backup para expor dados somente leitura do tipo MutableLiveData.
  • No objeto ViewModel, mude o tipo dos dados para private MutableLiveData. Use uma propriedade de backup para expor dados somente leitura do tipo LiveData.
  • No controlador de IU, mude o tipo de dados para private MutableLiveData. Use uma propriedade de backup para expor dados somente leitura do tipo LiveData.
  • No objeto ViewModel, mude o tipo dos dados para LiveData. Use uma propriedade de backup para expor dados somente leitura do tipo LiveData.

Pergunta 2

LiveData atualizará um controlador de IU (como um fragmento) se ele estiver em qual dos seguintes estados?

  • Retomado
  • Em segundo plano
  • Pausado
  • Interrompido

Pergunta 3

No padrão do observador LiveData, qual é o item observável (o que é observado)?

  • O método do observador
  • Os dados em um objeto LiveData
  • O controlador de IU
  • O objeto ViewModel

Inicie a próxima lição: 5.3: Vinculação de dados com o ViewModel e o LiveData

Para ver links de outros codelabs neste curso, consulte a página de destino dos codelabs do curso Conceitos básicos do Kotlin para Android.