Concetti fondamentali di Android Kotlin 05.2: osservatori di LiveData e LiveData

Questo codelab fa parte del corso Android Kotlin Fundamentals. Otterrai il massimo valore da questo corso se lavori in sequenza nei codelab. Tutti i codelab del corso sono elencati nella pagina di destinazione di Android Kotlin Fundamentals.

Introduzione

Nel codelab precedente, hai utilizzato un elemento ViewModel nell'app GuessTheWord per consentire ai dati dell'app di sopravvivere alle modifiche della configurazione del dispositivo. In questo codelab, imparerai a integrare LiveData con i dati delle classi ViewModel. LiveData, che è uno dei componenti dell'architettura Android, ti consente di creare oggetti di dati che avvisano le viste quando cambia il database sottostante.

Per utilizzare la classe LiveData, devi configurare"osservatori", ad esempio attività o frammenti, che osservano le modifiche nei dati dell'app. LiveData è in grado di rilevare il ciclo di vita, pertanto aggiorna solo gli utenti che osservano i componenti dell'app che si trovano in uno stato di ciclo di vita attivo.

Informazioni importanti

  • Come creare app Android di base in Kotlin.
  • Come navigare tra le destinazioni della tua app.
  • Ciclo di vita di attività e frammenti.
  • Come utilizzare gli oggetti ViewModel nella tua app
  • Come creare oggetti ViewModel utilizzando l'interfaccia di ViewModelProvider.Factory.

Obiettivi didattici

  • Perché gli oggetti LiveData sono utili.
  • Come aggiungere LiveData ai dati archiviati in un ViewModel.
  • Quando e come utilizzare MutableLiveData.
  • Come aggiungere metodi di osservazione per osservare le modifiche nel LiveData.
  • Come incapsulare LiveData utilizzando una proprietà di supporto.
  • Come comunicare tra un controller UI e il ViewModel corrispondente.

In questo lab proverai a:

  • Usa LiveData per la parola e il punteggio nell'app GuessTheWord.
  • Aggiungi osservatori che rilevano la modifica della parola o del punteggio.
  • Aggiornare le visualizzazioni di testo che mostrano i valori modificati.
  • Utilizza il pattern Osservatore LiveData per aggiungere un evento completato dal gioco.
  • Implementa il pulsante Riproduci di nuovo.

Nei codelab della Lezione 5, sviluppi l'app GuessTheWord, iniziando con il codice di avvio. GuessTheWord è un gioco in stile charade per giocatori, in cui i giocatori collaborano per raggiungere il punteggio più alto possibile.

Il primo giocatore controlla le parole nell'app e le reagisce a turno, assicurandoti di non mostrare la parola al secondo giocatore. Il secondo giocatore prova a indovinare la parola.

Per giocare, il primo giocatore apre l'app sul dispositivo e vede una parola, ad esempio "chitarra", come mostrato nello screenshot di seguito.

Il primo giocatore pronuncia la parola, facendo attenzione a non pronunciare la parola stessa.

  • Quando il secondo giocatore indovina la parola correttamente, il primo pulsante preme il pulsante OK, che aumenta il conteggio di uno e mostra la parola successiva.
  • Se il secondo giocatore non riesce a indovinare la parola, il primo giocatore preme il pulsante Ignora: in questo modo il numero viene ridotto di uno e passa alla parola successiva.
  • Per terminare il gioco, premi il pulsante Termina gioco. Questa funzionalità non è presente nel codice di avvio del primo codelab della serie.

In questo codelab, puoi migliorare l'app GuessTheWord aggiungendo un evento che termina il gioco quando l'utente scorre tutte le parole dell'app. Aggiungi anche un pulsante Gioca di nuovo nel frammento del punteggio, in modo che l'utente possa giocare di nuovo.

Schermata del titolo

Schermata di gioco

Schermata punteggio

In questa attività, troverai ed eseguirai il tuo codice di avvio per questo codelab. Puoi usare come codice di avvio l'app GuessTheWord che hai creato nel codelab precedente oppure puoi scaricare un'app iniziale.

  1. (Facoltativo) Se non utilizzi il codice del codelab precedente, scarica il codice di avvio per questo codelab. Decomprimi il codice e apri il progetto in Android Studio.
  2. Esegui l'app e gioca.
  3. Tieni presente che il pulsante Ignora mostra la parola successiva e riduce il punteggio di uno, mentre il pulsante OK mostra la parola successiva e aumenta il punteggio di uno. Il pulsante Termina gioco consente di terminare il gioco.

LiveData è una classe di dati osservabili che tiene conto del ciclo di vita. Ad esempio, puoi aggregare un LiveData al punteggio attuale nell'app GuessTheWord. In questo codelab, puoi conoscere varie caratteristiche di LiveData:

  • LiveData è osservabile, il che significa che un osservatore riceve una notifica quando i dati contenuti nell'oggetto LiveData cambiano.
  • LiveData contiene dati; LiveData è un wrapper utilizzabile con qualsiasi dato
  • LiveData è sensibile al ciclo di vita, il che significa che aggiorna solo gli osservatori che si trovano in uno stato di ciclo di vita attivo, come STARTED o RESUMED.

In questa attività imparerai a includere qualsiasi tipo di dati negli oggetti LiveData convertendo il punteggio corrente e i dati delle parole correnti in GameViewModel in LiveData. In un'attività successiva, aggiungi un osservatore a questi oggetti LiveData e scopri come osservare LiveData.

Passaggio 1. Modifica il punteggio e la parola per utilizzare LiveData

  1. Nel pacchetto screens/game, apri il file GameViewModel.
  2. Cambia il tipo di variabile score e word in MutableLiveData.

    MutableLiveData è un LiveData di cui è possibile modificare il valore. MutableLiveData è una classe generica, quindi devi specificare il tipo di dati che contiene.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
  1. In GameViewModel, all'interno del blocco init, inizializza score e word. Per modificare il valore di una variabile LiveData, devi utilizzare il metodo setValue(). In Kotlin puoi chiamare setValue() utilizzando la proprietà value.
init {

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

Passaggio 2: aggiorna il riferimento all'oggetto LiveData

Le variabili score e word sono ora di tipo LiveData. In questo passaggio, modificherai i riferimenti a queste variabili utilizzando la proprietà value.

  1. In GameViewModel, nel metodo onSkip(), modifica score in score.value. Nota l'errore score che potrebbe essere relativo a null. Ora devi correggere questo errore.
  2. Per risolvere l'errore, aggiungi un controllo null a score.value in onSkip(). Quindi chiama la funzione minus() su score, che esegue la sottrazione con null-safety.
fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}
  1. Aggiorna il metodo onCorrect() nello stesso modo: aggiungi un controllo null alla variabile score e utilizza la funzione plus().
fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}
  1. In GameViewModel, all'interno del metodo nextWord(), modifica il riferimento word in word.value.
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}
  1. In GameFragment, all'interno del metodo updateWordText(), modifica il riferimento in viewModel.word in viewModel.word.value.
/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}
  1. In GameFragment, all'interno del metodo updateScoreText(), cambia il riferimento in viewModel.score in viewModel.score.value.
private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}
  1. In GameFragment, all'interno del metodo gameFinished(), modifica il riferimento in viewModel.score in viewModel.score.value. Aggiungi il controllo di sicurezza null obbligatorio.
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. Assicurati che il codice non contenga errori. Compila ed esegui la tua app. La funzionalità dell'app deve essere invariata.

Questa attività è strettamente correlata all'attività precedente, in cui hai convertito i dati del punteggio e delle parole in oggetti LiveData. In questa attività, dovrai collegare oggetti Observer a tali oggetti LiveData.

  1. In GameFragment, all'interno del metodo onCreateView(), collega un oggetto Observer all'oggetto LiveData per il punteggio attuale, viewModel.score. Usa il metodo observe() e inserisci il codice dopo l'inizializzazione di viewModel. Utilizza un'espressione lambda per semplificare il codice. Un'espressione lambda è una funzione anonima che non viene dichiarata, ma che viene trasmessa immediatamente come espressione.
viewModel.score.observe(this, Observer { newScore ->
})

Risolvi il riferimento a Observer. Per farlo, fai clic su Observer, premi Alt+Enter (Option+Enter su un Mac) e importa androidx.lifecycle.Observer.

  1. L'osservatore che hai appena creato riceve un evento quando i dati contenuti nell'oggetto LiveData osservato cambiano. All'interno di chi osserva la classifica, aggiorna il punteggio TextView con il nuovo punteggio.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. Allega un oggetto Observer all'oggetto parola LiveData corrente. Esegui la stessa operazione con l'aggiunta di un oggetto Observer al punteggio corrente.
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})

Quando il valore di score o di word cambia, i valori di score o word visualizzati sullo schermo ora vengono aggiornati automaticamente.

  1. In GameFragment, elimina i metodi updateWordText() e updateScoreText(), nonché tutti i riferimenti a questi metodi. Non ne hai più bisogno, perché le visualizzazioni del testo vengono aggiornate con i metodi osservatore LiveData.
  2. Esegui la tua app. L'app di gioco dovrebbe funzionare come prima, ma ora utilizza LiveData e LiveData osservatori.

L'incapsulamento è un modo per limitare l'accesso diretto ad alcuni campi dell'oggetto. Quando incapsula un oggetto, esponi un insieme di metodi pubblici che modificano i campi interni privati. Utilizzando l'incapsulamento, puoi controllare il modo in cui le altre classi manipolano questi campi interni.

Nel codice attuale, qualsiasi classe esterna può modificare le variabili score e word utilizzando la proprietà value, ad esempio utilizzando viewModel.score.value. Indipendentemente dall'app che stai sviluppando in questo codelab, tieni presente che in un'app di produzione vuoi il controllo dei dati negli oggetti ViewModel.

Solo ViewModel può modificare i dati nella tua app. Tuttavia, i controller dell'interfaccia utente devono leggere i dati, di conseguenza i campi dei dati non possono essere completamente privati. Per incapsulare i dati dell'app, si utilizzano gli oggetti MutableLiveData e LiveData.

MutableLiveData rispetto a LiveData:

  • I dati in un oggetto MutableLiveData possono essere modificati, come indica il nome. All'interno di ViewModel, i dati dovrebbero essere modificabili, pertanto utilizzano MutableLiveData.
  • I dati in un oggetto LiveData possono essere letti, ma non modificati. Al di fuori di ViewModel, i dati devono essere leggibili, ma non modificabili, quindi devono essere esposti come LiveData.

Per mettere in pratica questa strategia, utilizza una proprietà di supporto Kotlin. Una proprietà di supporto consente di restituire un elemento da un getter diverso dall'oggetto esatto. In questa attività implementerai una proprietà di supporto per gli oggetti score e word nell'app GuessTheWord.

Aggiungi una proprietà di supporto al punteggio e alla parola

  1. In GameViewModel, imposta l'oggetto score corrente come private.
  2. Per seguire la convenzione di denominazione utilizzata nelle proprietà di supporto, cambia score in _score. Ora la proprietà _score è la versione modificabile del punteggio del gioco da utilizzare internamente.
  3. Crea una versione pubblica di tipo LiveData, denominata score.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
  1. Viene visualizzato un errore di inizializzazione. Questo errore si verifica perché all'interno di GameFragment, score è un riferimento di LiveData e score non può più accedere al setter. Per scoprire di più su getter e setter in Kotlin, vedi Getter e setter.

    Per risolvere l'errore, esegui l'override del metodo get() per l'oggetto score in GameViewModel e restituisci la proprietà di supporto, _score.
val score: LiveData<Int>
   get() = _score
  1. In GameViewModel, modifica i riferimenti di score alla sua versione modificabile 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. Rinomina l'oggetto word in _word e aggiungi una proprietà di supporto, come hai fatto per l'oggetto 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)
   }
}

Ottimo lavoro, hai incapsulato gli oggetti LiveData word e score.

L'app corrente passa alla schermata del punteggio quando l'utente tocca il pulsante Termina gioco. Vuoi anche che l'app acceda alla schermata del punteggio quando i giocatori passano da una parola all'altra. Dopo che i giocatori hanno finito con l'ultima parola, vuoi che il gioco termini automaticamente, in modo che l'utente non debba toccare il pulsante.

Per implementare questa funzionalità, devi attivare un evento e comunicarlo al frammento da ViewModel quando tutte le parole sono state mostrate. Per farlo, utilizza il pattern osservatore LiveData per modellare un evento completato nel gioco.

Il pattern dell'osservatore

Il pattern dell'osservatore è un pattern di progettazione del software. Specifica la comunicazione tra gli oggetti: un osservabile (l'oggetto "osservatorio" dell'osservazione) e osservatori. Un oggetto osservabile è un oggetto che notifica agli osservatori i cambiamenti nel proprio stato.

Nel caso di LiveData in questa app, l'osservatore (oggetto) è l'oggetto LiveData e gli osservatori sono i metodi nei controller dell'interfaccia utente, come i frammenti. Ogni volta che i dati inseriti nel codice LiveData vengono modificati, viene applicata una modifica di stato. Le classi LiveData sono fondamentali per comunicare da ViewModel al frammento.

Passaggio 1: usa LiveData per rilevare un evento completato dal gioco

In questa attività, utilizzerai il pattern osservatore LiveData per modellare un evento completato nel gioco.

  1. In GameViewModel, crea un oggetto Boolean MutableLiveData chiamato _eventGameFinish. Questo oggetto conterrà l'evento completato nel gioco.
  2. Dopo aver inizializzato l'oggetto _eventGameFinish, crea e inizializza una proprietà di supporto denominata eventGameFinish.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
   get() = _eventGameFinish
  1. In GameViewModel, aggiungi un metodo onGameFinish(). Nel metodo, imposta l'evento completato nel gioco, eventGameFinish, su true.
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. In GameViewModel, all'interno del metodo nextWord(), termina il gioco se l'elenco di parole è vuoto.
private fun nextWord() {
   if (wordList.isEmpty()) {
       onGameFinish()
   } else {
       //Select and remove a _word from the list
       _word.value = wordList.removeAt(0)
   }
}
  1. In GameFragment, all'interno di onCreateView(), dopo aver inizializzato viewModel, allega un osservatore a eventGameFinish. Utilizza il metodo observe(). All'interno della funzione lambda, chiama il metodo gameFinished().
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
   if (hasFinished) gameFinished()
})
  1. Esegui l'app, usa il gioco e rivedi tutte le parole. L'app passa automaticamente alla schermata del punteggio, anziché rimanere nel frammento del gioco finché non tocchi Termina gioco.

    Dopo aver vuoto l'elenco di parole, viene impostato eventGameFinish, viene chiamato il metodo di osservazione associato nel frammento del gioco e l'app passa al frammento dello schermo.
  2. Il codice aggiunto ha introdotto un problema del ciclo di vita. Per capire il problema, aggiungi un codice di navigazione nel metodo gameFinished() nella classe GameFragment. Assicurati di conservare il messaggio Toast nel metodo.
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. Esegui l'app, usa il gioco e rivedi tutte le parole. Nella parte inferiore dello schermo viene visualizzato per poco tempo un messaggio toast che indica che il gioco è appena terminato.

Ora ruota il dispositivo o l'emulatore. Toast di nuovo visualizzato! Ruota il dispositivo un paio di volte e probabilmente vedrai il toast ogni volta. Questo è un bug, perché il toast dovrebbe essere visualizzato solo una volta, quando il gioco è terminato. Il toast non deve essere visualizzato ogni volta che un frammento viene ricreato. Risolvi il problema nella prossima attività.

Passaggio 2: reimposta l'evento completato

In genere, LiveData offre aggiornamenti agli osservatori solo quando i dati cambiano. Un'eccezione a questo comportamento è che gli osservatori ricevono anche aggiornamenti quando lo spettatore passa da inattivo a attivo.

Questo è il motivo per cui il toast completato nel gioco viene attivato ripetutamente nell'app. Quando il frammento del gioco viene ricreato dopo una rotazione dello schermo, passa da uno stato inattivo a uno attivo. L'osservatore nel frammento viene ricollegato alla ViewModel esistente e riceve i dati correnti. Il metodo gameFinished() viene riattivato e viene visualizzato il toast.

In questa attività, risolvi il problema e visualizzi il toast una sola volta, reimpostando il flag eventGameFinish in GameViewModel.

  1. In GameViewModel, aggiungi un metodo onGameFinishComplete() per reimpostare l'evento di fine del gioco, _eventGameFinish.
/** Method for the game completed event **/

fun onGameFinishComplete() {
   _eventGameFinish.value = false
}
  1. In GameFragment, alla fine di gameFinished(), chiama onGameFinishComplete() nell'oggetto viewModel. (per ora lascia un commento nel codice di navigazione in gameFinished()).
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. Esegui l'app e gioca. Rileggi tutte le parole, quindi modifica l'orientamento dello schermo del dispositivo. La notifica toast viene visualizzata una sola volta.
  2. In GameFragment, all'interno del metodo gameFinished(), rimuovi il commento dal codice di navigazione.

    Per annullare il commento in Android Studio, seleziona le righe che sono state commentate e premi Control+/ (Command+/ su 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()
}

Se richiesto da Android Studio, importa androidx.navigation.fragment.NavHostFragment.findNavController.

  1. Esegui l'app e gioca. Assicurati che l'app passi automaticamente alla schermata del punteggio finale dopo aver letto tutte le parole.

Ottimo. La tua app utilizza LiveData per attivare un evento terminato dal gioco per comunicare da GameViewModel al frammento del gioco che indica che l'elenco di parole è vuoto. Il frammento del gioco passa quindi al frammento del punteggio.

In questa attività, modifichi il punteggio in un oggetto LiveData in ScoreViewModel e colleghi un osservatore. L'attività è simile a quella che hai eseguito quando hai aggiunto LiveData a GameViewModel.

Tu apporti queste modifiche a ScoreViewModel per completezza, in modo che tutti i dati della tua app utilizzino LiveData.

  1. In ScoreViewModel, modifica il tipo di variabile score in MutableLiveData. Rinominalo come convenzione per _score e aggiungi una proprietà di supporto.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
   get() = _score
  1. In ScoreViewModel, all'interno del blocco init, inizializza _score. Puoi rimuovere o lasciare il log nel blocco init come preferisci.
init {
   _score.value = finalScore
}
  1. In ScoreFragment, all'interno di onCreateView(), dopo aver inizializzato viewModel, allega un osservatore per l'oggetto punteggio LiveData. All'interno dell'espressione lambda, imposta il valore del punteggio sulla visualizzazione del testo del punteggio. Rimuovi da ViewModel il codice che assegna direttamente la visualizzazione di testo con il valore del punteggio.

Codice da aggiungere:

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

Codice da rimuovere:

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

Quando richiesto da Android Studio, importa androidx.lifecycle.Observer.

  1. Esegui l'app e gioca. L'app dovrebbe funzionare come prima, ma ora utilizza LiveData e un osservatore per aggiornare il punteggio.

In questa attività, aggiungi un pulsante Riproduci di nuovo nella schermata del punteggio e implementa il listener di clic utilizzando un evento LiveData. Il pulsante attiva un evento per passare dalla schermata del punteggio alla schermata del gioco.

Il codice di avvio dell'app include il pulsante Riproduci di nuovo, ma è nascosto.

  1. In res/layout/score_fragment.xml, per il pulsante play_again_button, cambia il valore dell'attributo visibility in visible.
<Button
   android:id="@+id/play_again_button"
...
   android:visibility="visible"
 />
  1. In ScoreViewModel, aggiungi un oggetto LiveData per contenere un Boolean chiamato _eventPlayAgain. Questo oggetto viene utilizzato per salvare l'evento LiveData per passare dalla schermata del punteggio alla schermata del gioco.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. In ScoreViewModel, definisci i metodi per impostare e reimpostare l'evento, _eventPlayAgain.
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. In ScoreFragment, aggiungi un osservatore per eventPlayAgain. Inserisci il codice alla fine di onCreateView(), prima dell'istruzione return. All'interno dell'espressione lambda, torna alla schermata del gioco e reimposta eventPlayAgain.
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
   if (playAgain) {
      findNavController().navigate(ScoreFragmentDirections.actionRestart())
       viewModel.onPlayAgainComplete()
   }
})

Importa androidx.navigation.fragment.findNavController, quando richiesto da Android Studio.

  1. In ScoreFragment, all'interno di onCreateView(), aggiungi un listener di clic al pulsante PlayAgain e chiama viewModel.onPlayAgain().
binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. Esegui l'app e gioca. Al termine della partita, nella schermata dei punteggi viene visualizzato il punteggio finale e il pulsante Gioca di nuovo. Tocca il pulsante PlayAgain e l'app va alla schermata del gioco per giocare di nuovo.

Ottimo! Hai modificato l'architettura della tua app in modo da utilizzare gli oggetti LiveData in ViewModel e hai associato gli osservatori agli oggetti LiveData. LiveData avvisa gli oggetti dell'osservatore quando cambia il valore detenuto da LiveData.

Progetto Android Studio: GuessTheWord

Dati LiveLive

  • LiveData è una classe di dati osservabili sensibile al ciclo di vita, uno dei componenti dell'architettura Android.
  • Puoi usare LiveData per attivare l'aggiornamento automatico dell'interfaccia utente quando i dati vengono aggiornati.
  • LiveData è osservabile, il che significa che un osservatore come un'attività o un frammento può essere avvisato quando i dati contenuti nell'oggetto LiveData cambiano.
  • LiveData contiene dati; è un wrapper che può essere utilizzato con qualsiasi dato.
  • LiveData è sensibile al ciclo di vita, il che significa che aggiorna solo gli osservatori che si trovano in uno stato di ciclo di vita attivo, come STARTED o RESUMED.

Aggiungere LiveData

  • Cambia il tipo di variabili dei dati in ViewModel in LiveData o MutableLiveData.

MutableLiveData è un oggetto LiveData il cui valore può essere modificato. MutableLiveData è una classe generica, quindi devi specificare il tipo di dati che contiene.

  • Per modificare il valore dei dati detenuti da LiveData, utilizza il metodo setValue() sulla variabile LiveData.

Per incapsulare i LiveData

  • LiveData all'interno di ViewModel deve essere modificabile. Al di fuori di ViewModel, il campo LiveData deve essere leggibile. Puoi implementarlo utilizzando una proprietà di supporto Kotlin.
  • Una proprietà di supporto Kotlin ti consente di restituire qualcosa da un getter diverso dall'oggetto esatto.
  • Per incapsulare il LiveData, utilizza private MutableLiveData all'interno di ViewModel e restituisci una proprietà di supporto LiveData al di fuori di ViewModel.

LiveData osservabili

  • LiveData segue uno schema di osservazione. L'oggetto"osservabile"è l'oggetto LiveData e gli osservatori sono i metodi nei controller dell'interfaccia utente, come i frammenti. Ogni volta che i dati aggregati all'interno di LiveData cambiano, i metodi di osservazione nei controller dell'interfaccia utente vengono informati.
  • Per rendere osservabile LiveData, collega un oggetto osservatore al riferimento LiveData in osservatori (come attività e frammenti) utilizzando il metodo observe().
  • Questo pattern di osservazione LiveData può essere utilizzato per comunicare da ViewModel ai controller dell'interfaccia utente.

Corso Udacity:

Documentazione per gli sviluppatori Android:

Altro:

In questa sezione sono elencati i possibili compiti per gli studenti che lavorano attraverso questo codelab nell'ambito di un corso tenuto da un insegnante. Spetta all'insegnante fare quanto segue:

  • Assegna i compiti, se necessario.
  • Comunica agli studenti come inviare compiti.
  • Valuta i compiti.

Gli insegnanti possono utilizzare i suggerimenti solo quanto e come vogliono e dovrebbero assegnare i compiti che ritengono appropriati.

Se stai lavorando da solo a questo codelab, puoi utilizzare questi compiti per mettere alla prova le tue conoscenze.

Rispondi a queste domande

Domanda 1

Come incapsula il LiveData archiviato in un ViewModel in modo che gli oggetti esterni possano leggere i dati senza poterli aggiornare?

  • Modifica il tipo di dati nell'oggetto ViewModel impostandolo su private LiveData. Utilizza una proprietà di supporto per esporre i dati di sola lettura del tipo MutableLiveData.
  • Modifica il tipo di dati nell'oggetto ViewModel impostandolo su private MutableLiveData. Utilizza una proprietà di supporto per esporre i dati di sola lettura del tipo LiveData.
  • All'interno del controller dell'interfaccia utente, modifica il tipo di dati in private MutableLiveData. Utilizza una proprietà di supporto per esporre i dati di sola lettura del tipo LiveData.
  • Modifica il tipo di dati nell'oggetto ViewModel impostandolo su LiveData. Utilizza una proprietà di supporto per esporre i dati di sola lettura del tipo LiveData.

Domanda 2

LiveData aggiorna un controller dell'interfaccia utente (ad esempio un frammento) se si trova in quale dei seguenti stati?

  • Hai ripreso
  • In background
  • In pausa
  • Arrestata

Domanda 3

Nel modello dell'osservatore LiveData, qual è l'elemento osservabile (cosa viene osservato)?

  • Il metodo osservatore
  • I dati in un oggetto LiveData
  • Il controller dell'interfaccia utente
  • L'oggetto ViewModel

Inizia la lezione successiva: 5.3: Associazione di dati con ViewModel e LiveData

Per i link ad altri codelab in questo corso, consulta la pagina di destinazione di Android Kotlin Fundamentals.