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 interfaceViewModelProvider.Factory
.
O que você vai aprender
- O que torna objetos
LiveData
úteis. - Como adicionar um
LiveData
aos dados armazenados em umViewModel
. - 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.
- (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.
- Execute o app e jogue.
- 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 objetoLiveData
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, comoSTARTED
ouRESUMED
.
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
- No pacote
screens/game
, abra o arquivoGameViewModel
. - Mude o tipo das variáveis
score
eword
paraMutableLiveData
.MutableLiveData
é umLiveData
cujo valor pode ser alterado. AMutableLiveData
é 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>()
- No
GameViewModel
, dentro do blocoinit
, inicializescore
eword
. Para mudar o valor de uma variávelLiveData
, use o métodosetValue()
nela. No Kotlin, você pode chamarsetValue()
usando a propriedadevalue
.
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
.
- Em
GameViewModel
, no métodoonSkip()
, mudescore
parascore.value
. O erro sobrescore
pode sernull
. O erro será corrigido a seguir. - Para resolver o erro, adicione uma verificação
null
ascore.value
emonSkip()
. Em seguida, chame a funçãominus()
noscore
, que executa a subtração com a segurançanull
.
fun onSkip() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.minus(1)
}
nextWord()
}
- Atualize o método
onCorrect()
da mesma forma: adicione uma verificaçãonull
à variávelscore
e use a funçãoplus()
.
fun onCorrect() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.plus(1)
}
nextWord()
}
- No
GameViewModel
, no métodonextWord()
, mude a referênciaword
paraword
.
value
.
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}
- No
GameFragment
, no métodoupdateWordText()
, mude a referência paraviewModel
.word
paraviewModel
.
word
.
value.
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}
- No
GameFragment
, no métodoupdateScoreText()
, mude a referência paraviewModel
.score
paraviewModel
.
score
.
value.
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}
- No
GameFragment
, no métodogameFinished()
, mude a referência paraviewModel
.score
paraviewModel
.
score
.
value
. Adicione a confirmação de segurançanull
.
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)
}
- 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
.
- No
GameFragment,
no métodoonCreateView()
, anexe um objetoObserver
ao objetoLiveData
para a pontuação atual,viewModel.score
. Use o métodoobserve()
e coloque o código após a inicialização doviewModel
. 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
.
- O observador que você acabou de criar recebe um evento quando os dados retidos pelo objeto
LiveData
observado mudam. No observador, atualize a pontuaçãoTextView
com a nova pontuação.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
- Anexe um objeto
Observer
ao objeto atual da palavraLiveData
. Faça isso da mesma forma que você anexou um objetoObserver
à 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.
- No
GameFragment
, exclua os métodosupdateWordText()
eupdateScoreText()
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 doLiveData
. - Execute o app. Seu app de jogo funcionará exatamente como antes, mas agora usa os observadores
LiveData
eLiveData
.
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. NoViewModel
, os dados precisam ser editáveis. Portanto, ele usaMutableLiveData
. - Os dados em um objeto
LiveData
podem ser lidos, mas não alterados. Fora doViewModel
, os dados precisam ser legíveis, mas não editáveis, portanto, os dados precisam ser expostos comoLiveData
.
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
- Em
GameViewModel
, torne o objetoscore
atualprivate
. - 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. - Crie uma versão pública do tipo
LiveData
, chamadascore
.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
- Você verá um erro de inicialização. Esse erro ocorre porque, dentro do
GameFragment
, oscore
é uma referênciaLiveData
, e oscore
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étodoget()
do objetoscore
emGameViewModel
e retorne a propriedade de apoio_score
.
val score: LiveData<Int>
get() = _score
- No
GameViewModel
, mude as referências descore
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)
}
...
}
- Renomeie o objeto
word
como_word
e adicione uma propriedade de apoio, como você fez para o objetoscore
.
// 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.
- No
GameViewModel
, crie um objetoBoolean
MutableLiveData
chamado_eventGameFinish
. Esse objeto conterá o evento finalizado do jogo. - Depois de inicializar o objeto
_eventGameFinish
, crie e inicialize uma propriedade de apoio chamadaeventGameFinish
.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinish
- No
GameViewModel
, adicione um métodoonGameFinish()
. No método, defina o evento finalizado do jogo,eventGameFinish
, comotrue
.
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}
- No
GameViewModel
, no métodonextWord()
, 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)
}
}
- No
GameFragment
, no métodoonCreateView()
, depois de inicializar oviewModel
, anexe um observador aoeventGameFinish
. Use o métodoobserve()
. Dentro da função lambda, chame o métodogameFinished()
.
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
if (hasFinished) gameFinished()
})
- 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, oeventGameFinish
é definido, o método de observador associado no fragmento do jogo é chamado, e o app navega para o fragmento de tela. - 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étodogameFinished()
. Mantenha a mensagemToast
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)
}
- 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
.
- No
GameViewModel
, adicione um métodoonGameFinishComplete()
para redefinir o evento concluído do jogo,_eventGameFinish
.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}
- No
GameFragment
ao final degameFinished()
, chameonGameFinishComplete()
no objetoviewModel
. Deixe o código de navegação emgameFinished()
comentado por enquanto.
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}
- 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.
- No
GameFragment
, no métodogameFinished()
, 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 pressioneControl+/
(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
.
- 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
.
- No
ScoreViewModel
, mude o tipo da variávelscore
paraMutableLiveData
. Renomeie-o por_score
e adicione uma propriedade de apoio.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
- No
ScoreViewModel
, dentro do blocoinit
, inicialize o_score
. Você pode remover ou deixar o registro no blocoinit
como quiser.
init {
_score.value = finalScore
}
- No
ScoreFragment
, no métodoonCreateView()
, depois de inicializar oviewModel
, anexe um observador para o objeto de pontuaçãoLiveData
. 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 daViewModel
.
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
.
- 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.
- Em
res/layout/score_fragment.xml
, para o botãoplay_again_button
, altere o valor do atributovisibility
paravisible
.
<Button
android:id="@+id/play_again_button"
...
android:visibility="visible"
/>
- No
ScoreViewModel
, adicione um objetoLiveData
para armazenar umBoolean
chamado_eventPlayAgain
. Esse objeto é usado para salvar o eventoLiveData
para navegar da tela de pontuação para a tela do jogo.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgain
- Em
ScoreViewModel
, defina métodos para definir e redefinir o evento,_eventPlayAgain
.
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}
- No
ScoreFragment
, adicione um observador para oeventPlayAgain
. Coloque o código no final deonCreateView()
, antes da instruçãoreturn
. Na expressão lambda, navegue de volta para a tela do jogo e redefina oeventPlayAgain
.
// 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.
- No
ScoreFragment
, no métodoonCreateView()
, adicione um listener de clique ao botão PlayAgain e chameviewModel
.onPlayAgain()
.
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }
- 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 objetoLiveData
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, comoSTARTED
ouRESUMED
.
Adicionar o LiveData
- Mude o tipo das variáveis de dados na
ViewModel
paraLiveData
ouMutableLiveData
.
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étodosetValue()
na variávelLiveData
.
Para encapsular o LiveData
- O
LiveData
noViewModel
precisa ser editável. Fora doViewModel
, oLiveData
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
, useprivate
MutableLiveData
dentro daViewModel
e retorne uma propriedade de apoioLiveData
fora daViewModel
.
LiveData observável
LiveData
segue um padrão de observador. O "observable" é o objetoLiveData
, e os observadores são os métodos nos controladores de IU, como fragmentos. Sempre que os dados agrupados noLiveData
mudarem, os métodos do observador nos controladores de IU serão notificados.- Para tornar o
LiveData
observável, anexe um objeto observador à referênciaLiveData
nos observadores (como atividades e fragmentos) usando o métodoobserve()
. - Esse padrão de observador
LiveData
pode ser usado para comunicação entre osViewModel
e os controladores de IU.
Curso da Udacity:
- Como desenvolver apps Android com Kotlin (link em inglês)
Documentação do desenvolvedor Android:
Outro:
- Propriedade de apoio (link em inglês) no Kotlin
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 paraprivate
LiveData
. Use uma propriedade de backup para expor dados somente leitura do tipoMutableLiveData
. - No objeto
ViewModel
, mude o tipo dos dados paraprivate
MutableLiveData
. Use uma propriedade de backup para expor dados somente leitura do tipoLiveData
. - No controlador de IU, mude o tipo de dados para
private
MutableLiveData
. Use uma propriedade de backup para expor dados somente leitura do tipoLiveData
. - No objeto
ViewModel
, mude o tipo dos dados paraLiveData
. Use uma propriedade de backup para expor dados somente leitura do tipoLiveData
.
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:
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.