Questo codelab fa parte del corso Android Kotlin Fundamentals. Per ottenere il massimo valore da questo corso, ti consigliamo di seguire le codelab in sequenza. Tutti i codelab del corso sono elencati nella pagina di destinazione dei codelab Android Kotlin Fundamentals.
Introduzione
Nel codelab precedente, hai utilizzato un ViewModel
nell'app GuessTheWord per consentire ai dati dell'app di sopravvivere alle modifiche alla configurazione del dispositivo. In questo codelab, imparerai a integrare LiveData
con i dati nelle classi ViewModel
. LiveData
, uno dei componenti dell'architettura Android, ti consente di creare oggetti di dati che notificano alle visualizzazioni le modifiche al database sottostante.
Per utilizzare la classe LiveData
, devi configurare "osservatori" (ad esempio attività o frammenti) che osservano le modifiche ai dati dell'app. LiveData
è consapevole del ciclo di vita, quindi aggiorna solo gli osservatori dei componenti dell'app che si trovano in uno stato del ciclo di vita attivo.
Cosa devi già sapere
- Come creare app per Android di base in Kotlin.
- Come spostarsi tra le destinazioni dell'app.
- Ciclo di vita di attività e frammenti.
- Come utilizzare gli oggetti
ViewModel
nella tua app. - Come creare oggetti
ViewModel
utilizzando l'interfacciaViewModelProvider.Factory
.
Obiettivi didattici
- Che cosa rende utili gli oggetti
LiveData
. - Come aggiungere
LiveData
ai dati archiviati in unViewModel
. - Quando e come utilizzare
MutableLiveData
. - Come aggiungere metodi di osservazione per osservare le modifiche in
LiveData.
- Come incapsulare
LiveData
utilizzando una proprietà di supporto. - Come comunicare tra un controller UI e il relativo
ViewModel
.
In questo lab proverai a:
- Utilizza
LiveData
per la parola e il punteggio nell'app IndovinaParola. - Aggiungi osservatori che notano quando la parola o il punteggio cambia.
- Aggiorna le visualizzazioni di testo che mostrano i valori modificati.
- Utilizza il pattern observer
LiveData
per aggiungere un evento di fine partita. - Implementa il pulsante Gioca di nuovo.
Nei codelab della lezione 5, sviluppi l'app IndovinaParola, partendo dal codice iniziale. IndovinaParola è un gioco in stile Sarabanda per due giocatori, in cui i giocatori collaborano per ottenere il punteggio più alto possibile.
Il primo giocatore guarda le parole nell'app e le mima a turno, assicurandosi di non mostrarle al secondo giocatore. Il secondo giocatore cerca di 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 recita la parola, facendo attenzione a non dirla.
- Quando il secondo giocatore indovina la parola correttamente, il primo giocatore preme il pulsante Indovinato, 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 Salta, che diminuisce il conteggio di uno e passa alla parola successiva.
- Per terminare la partita, premi il pulsante Termina partita. Questa funzionalità non è presente nel codice iniziale del primo codelab della serie.
In questo codelab, migliorerai l'app GuessTheWord aggiungendo un evento per terminare la partita quando l'utente ha esaurito tutte le parole dell'app. Aggiungerai anche un pulsante Gioca di nuovo nel fragment del punteggio, in modo che l'utente possa giocare di nuovo.
Schermata del titolo | Schermata di gioco | Schermata del punteggio |
In questa attività, individua ed esegui il codice iniziale per questo codelab. Puoi utilizzare l'app IndovinaParola che hai creato nel codelab precedente come codice iniziale oppure scaricare un'app iniziale.
- (Facoltativo) Se non utilizzi il codice del codelab precedente, scarica il codice iniziale per questo codelab. Decomprimi il codice e apri il progetto in Android Studio.
- Esegui l'app e gioca.
- Tieni presente che il pulsante Salta mostra la parola successiva e diminuisce il punteggio di uno, mentre il pulsante Capito mostra la parola successiva e aumenta il punteggio di uno. Il pulsante Termina partita termina la partita.
LiveData
è una classe di contenitore di dati osservabile che riconosce il ciclo di vita. Ad esempio, puoi racchiudere un LiveData
intorno al punteggio attuale nell'app IndovinaParola. In questo codelab, scoprirai diverse caratteristiche di LiveData
:
LiveData
è osservabile, il che significa che un osservatore riceve una notifica quando i dati contenuti nell'oggettoLiveData
cambiano.LiveData
contiene i dati;LiveData
è un wrapper che può essere utilizzato con qualsiasi datoLiveData
è consapevole del ciclo di vita, il che significa che aggiorna solo gli osservatori che si trovano in uno stato del ciclo di vita attivo, ad esempioSTARTED
oRESUMED
.
In questa attività, imparerai a racchiudere qualsiasi tipo di dati in oggetti LiveData
convertendo i dati relativi al punteggio attuale e alla parola attuale 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
- Nel pacchetto
screens/game
, apri il fileGameViewModel
. - Modifica il tipo delle variabili
score
eword
inMutableLiveData
.MutableLiveData
è unLiveData
il cui valore può essere modificato.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>()
- In
GameViewModel
, all'interno del bloccoinit
, inizializzascore
eword
. Per modificare il valore di una variabileLiveData
, utilizza il metodosetValue()
sulla variabile. In Kotlin, puoi chiamaresetValue()
utilizzando la proprietàvalue
.
init {
word.value = ""
score.value = 0
...
}
Passaggio 2: aggiorna il riferimento all'oggetto LiveData
Le variabili score
e word
ora sono di tipo LiveData
. In questo passaggio, modifichi i riferimenti a queste variabili utilizzando la proprietà value
.
- In
GameViewModel
, nel metodoonSkip()
, modificascore
inscore.value
. Nota l'errore relativo ascore
che potrebbe esserenull
. Correggi questo errore nel passaggio successivo. - Per risolvere l'errore, aggiungi un controllo
null
ascore.value
inonSkip()
. Poi chiama la funzioneminus()
suscore
, che esegue la sottrazione connull
-safety.
fun onSkip() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.minus(1)
}
nextWord()
}
- Aggiorna il metodo
onCorrect()
nello stesso modo: aggiungi un controllonull
alla variabilescore
e utilizza la funzioneplus()
.
fun onCorrect() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.plus(1)
}
nextWord()
}
- In
GameViewModel
, all'interno del metodonextWord()
, modifica il riferimentoword
inword
.
value
.
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}
- In
GameFragment
, all'interno del metodoupdateWordText()
, modifica il riferimento aviewModel
.word
inviewModel
.
word
.
value.
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}
- In
GameFragment
, all'interno del metodoupdateScoreText()
, modifica il riferimento aviewModel
.score
inviewModel
.
score
.
value.
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}
- In
GameFragment
, all'interno del metodogameFinished()
, modifica il riferimento daviewModel
.score
aviewModel
.
score
.
value
. Aggiungi il controllo di sicurezzanull
richiesto.
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)
}
- Assicurati che non ci siano errori nel codice. Compila ed esegui l'app. La funzionalità dell'app dovrebbe essere la stessa di prima.
Questa attività è strettamente correlata a quella precedente, in cui hai convertito i dati di punteggio e parole in oggetti LiveData
. In questa attività, collegherai gli oggetti Observer
agli oggetti LiveData
.
- In
GameFragment,
all'interno del metodoonCreateView()
, collega un oggettoObserver
all'oggettoLiveData
per il punteggio corrente,viewModel.score
. Utilizza il metodoobserve()
e inserisci il codice dopo l'inizializzazione diviewModel
. Utilizza un'espressione lambda per semplificare il codice. Un'espressione lambda è una funzione anonima che non viene dichiarata, ma viene passata 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 Mac) e importa androidx.lifecycle.Observer
.
- L'osservatore che hai appena creato riceve un evento quando cambiano i dati contenuti nell'oggetto
LiveData
osservato. All'interno dell'osservatore, aggiorna il punteggioTextView
con il nuovo punteggio.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
- Allega un oggetto
Observer
all'oggetto parola correnteLiveData
. Fallo nello stesso modo in cui hai allegato un oggettoObserver
alla partitura 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, il valore di score
o word
visualizzato sullo schermo ora si aggiorna automaticamente.
- In
GameFragment
, elimina i metodiupdateWordText()
eupdateScoreText()
e tutti i relativi riferimenti. Non ne hai più bisogno, perché le visualizzazioni di testo vengono aggiornate dai metodi di osservazioneLiveData
. - Esegui l'app. L'app di gioco dovrebbe funzionare esattamente come prima, ma ora utilizza gli osservatori
LiveData
eLiveData
.
L'incapsulamento è un modo per limitare l'accesso diretto ad alcuni campi di un oggetto. Quando incapsuli un oggetto, esponi un insieme di metodi pubblici che modificano i campi interni privati. Utilizzando l'incapsulamento, controlli 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
. Potrebbe non essere importante nell'app che stai sviluppando in questo codelab, ma in un'app di produzione vuoi controllare i dati negli oggetti ViewModel
.
Solo ViewModel
deve modificare i dati nella tua app. Tuttavia, i controller UI devono leggere i dati, quindi i campi di dati non possono essere completamente privati. Per incapsulare i dati della tua app, utilizzi gli oggetti MutableLiveData
e LiveData
.
MutableLiveData
contro LiveData
:
- I dati in un oggetto
MutableLiveData
possono essere modificati, come suggerisce il nome. All'interno diViewModel
, i dati devono essere modificabili, quindi utilizzaMutableLiveData
. - I dati in un oggetto
LiveData
possono essere letti, ma non modificati. Al di fuori diViewModel
, i dati devono essere leggibili, ma non modificabili, quindi devono essere esposti comeLiveData
.
Per implementare questa strategia, utilizzi una proprietà di backing Kotlin. Una proprietà di supporto consente di restituire qualcosa da un getter diverso dall'oggetto esatto. In questa attività, implementerai una proprietà di supporto per gli oggetti score
e word
nell'app IndovinaParola.
Aggiungere una proprietà di supporto a punteggio e parola
- In
GameViewModel
, rendi l'oggettoscore
correnteprivate
. - Per seguire la convenzione di denominazione utilizzata nelle proprietà di backup, modifica
score
in_score
. La proprietà_score
è ora la versione modificabile del punteggio di gioco, da utilizzare internamente. - Crea una versione pubblica del tipo
LiveData
, denominatascore
.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
- Viene visualizzato un errore di inizializzazione. Questo errore si verifica perché all'interno di
GameFragment
,score
è un riferimentoLiveData
escore
non può più accedere al relativo setter. Per scoprire di più su getter e setter in Kotlin, consulta Getter e setter.
Per risolvere l'errore, esegui l'override del metodoget()
per l'oggettoscore
inGameViewModel
e restituisci la proprietà di supporto,_score
.
val score: LiveData<Int>
get() = _score
- In
GameViewModel
, modifica i riferimenti discore
alla relativa versione interna modificabile,_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)
}
...
}
- Rinomina l'oggetto
word
in_word
e aggiungi una proprietà di supporto, come hai fatto per l'oggettoscore
.
// 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 attuale passa alla schermata del punteggio quando l'utente tocca il pulsante Fine partita. Inoltre, vuoi che l'app passi alla schermata del punteggio quando i giocatori hanno completato tutti i cicli delle parole. Dopo che i giocatori hanno finito con l'ultima parola, vuoi che la partita termini automaticamente in modo che l'utente non debba toccare il pulsante.
Per implementare questa funzionalità, è necessario che venga attivato un evento e comunicato al fragment da ViewModel
quando sono state mostrate tutte le parole. Per farlo, utilizza il LiveData
pattern observer per modellare un evento di fine partita.
Il pattern Observer
Il pattern Observer è un pattern di progettazione del software. Specifica la comunicazione tra gli oggetti: un osservabile (il "soggetto" dell'osservazione) e gli osservatori. Un osservabile è un oggetto che notifica agli osservatori le modifiche al suo stato.
Nel caso di LiveData
in questa app, l'osservabile (soggetto) è l'oggetto LiveData
e gli osservatori sono i metodi nei controller UI, come i fragment. Una modifica dello stato si verifica ogni volta che cambiano i dati inclusi in LiveData
. Le classi LiveData
sono fondamentali per la comunicazione da ViewModel
al frammento.
Passaggio 1: utilizza LiveData per rilevare un evento di fine partita
In questa attività, utilizzi il pattern observer LiveData
per modellare un evento di fine partita.
- In
GameViewModel
, crea un oggettoBoolean
MutableLiveData
chiamato_eventGameFinish
. Questo oggetto conterrà l'evento di fine partita. - Dopo aver inizializzato l'oggetto
_eventGameFinish
, crea e inizializza una proprietà di supporto chiamataeventGameFinish
.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinish
- In
GameViewModel
, aggiungi un metodoonGameFinish()
. Nel metodo, imposta l'evento di fine partita,eventGameFinish
, sutrue
.
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}
- In
GameViewModel
, all'interno del metodonextWord()
, termina la partita 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)
}
}
- In
GameFragment
, all'interno dionCreateView()
, dopo aver inizializzatoviewModel
, collega un osservatore aeventGameFinish
. Utilizza il metodoobserve()
. All'interno della funzione lambda, chiama il metodogameFinished()
.
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
if (hasFinished) gameFinished()
})
- Esegui l'app, gioca e ripassa tutte le parole. L'app passa automaticamente alla schermata del punteggio, anziché rimanere nel frammento di gioco finché non tocchi Termina partita.
Una volta svuotato l'elenco di parole, viene impostatoeventGameFinish
, viene chiamato il metodo observer associato nel frammento di gioco e l'app passa al frammento di schermata. - Il codice che hai aggiunto ha introdotto un problema del ciclo di vita. Per comprendere il problema, nella classe
GameFragment
, commenta il codice di navigazione nel metodogameFinished()
. Assicurati di mantenere il messaggioToast
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)
}
- Esegui l'app, gioca e ripassa tutte le parole. Nella parte inferiore della schermata di gioco viene visualizzato brevemente un messaggio di notifica che indica "La partita è appena terminata", come previsto.
Ora ruota il dispositivo o l'emulatore. Il messaggio toast viene visualizzato di nuovo. Ruota il dispositivo altre volte e probabilmente vedrai il messaggio ogni volta. Si tratta di un bug, perché il messaggio di notifica dovrebbe essere visualizzato una sola volta, al termine della partita. Il toast non deve essere visualizzato ogni volta che il frammento viene ricreato. Risolvi questo problema nella prossima attività.
Passaggio 2: reimposta l'evento di fine partita
In genere, LiveData
invia aggiornamenti agli osservatori solo quando i dati cambiano. Un'eccezione a questo comportamento è che gli osservatori ricevono aggiornamenti anche quando passano da uno stato inattivo a uno attivo.
Per questo motivo, il messaggio di notifica di fine partita viene attivato ripetutamente nell'app. Quando il frammento di gioco viene ricreato dopo una rotazione dello schermo, passa da uno stato inattivo a uno stato attivo. L'observer nel fragment viene riconnesso all'ViewModel
esistente e riceve i dati correnti. Il metodo gameFinished()
viene riattivato e viene visualizzato il messaggio di notifica.
In questa attività, risolverai il problema e visualizzerai il messaggio di notifica solo una volta reimpostando il flag eventGameFinish
in GameViewModel
.
- In
GameViewModel
, aggiungi un metodoonGameFinishComplete()
per reimpostare l'evento di completamento della partita,_eventGameFinish
.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}
- In
GameFragment
, alla fine digameFinished()
, chiamaonGameFinishComplete()
sull'oggettoviewModel
. Per ora lascia il codice di navigazione commentato ingameFinished()
.
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}
- Esegui l'app e gioca. Leggi tutte le parole, quindi cambia l'orientamento dello schermo del dispositivo. Il messaggio popup viene visualizzato una sola volta.
- In
GameFragment
, all'interno del metodogameFinished()
, rimuovi il commento dal codice di navigazione.
Per rimuovere il commento in Android Studio, seleziona le righe commentate e premiControl+/
(Command+/
su 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
.
- Esegui l'app e gioca. Assicurati che l'app passi automaticamente alla schermata del punteggio finale dopo che hai completato tutte le parole.
Ottimo lavoro! La tua app utilizza LiveData
per attivare un evento di fine partita per comunicare da GameViewModel
al frammento di gioco che l'elenco di parole è vuoto. Il frammento di gioco passa quindi al frammento del punteggio.
In questa attività, modifichi il punteggio in un oggetto LiveData
in ScoreViewModel
e gli colleghi un osservatore. Questa attività è simile a quella che hai svolto quando hai aggiunto LiveData
a GameViewModel
.
Apporti queste modifiche a ScoreViewModel
per completezza, in modo che tutti i dati della tua app utilizzino LiveData
.
- In
ScoreViewModel
, modifica il tipo di variabilescore
inMutableLiveData
. Rinominalo per convenzione in_score
e aggiungi una proprietà di supporto.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
- In
ScoreViewModel
, all'interno del bloccoinit
, inizializza_score
. Puoi rimuovere o lasciare il log nel bloccoinit
come preferisci.
init {
_score.value = finalScore
}
- In
ScoreFragment
, all'interno dionCreateView()
, dopo aver inizializzatoviewModel
, collega un osservatore per l'oggettoLiveData
del punteggio. All'interno dell'espressione lambda, imposta il valore del punteggio sulla visualizzazione del testo del punteggio. Rimuovi il codice che assegna direttamente la visualizzazione del testo con il valore del punteggio daViewModel
.
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
.
- 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 Gioca di nuovo alla schermata del punteggio e implementa il relativo listener di clic utilizzando un evento LiveData
. Il pulsante attiva un evento per passare dalla schermata del punteggio alla schermata di gioco.
Il codice iniziale dell'app include il pulsante Gioca di nuovo, ma è nascosto.
- In
res/layout/score_fragment.xml
, per il pulsanteplay_again_button
, modifica il valore dell'attributovisibility
invisible
.
<Button
android:id="@+id/play_again_button"
...
android:visibility="visible"
/>
- In
ScoreViewModel
, aggiungi un oggettoLiveData
per contenere unBoolean
chiamato_eventPlayAgain
. Questo oggetto viene utilizzato per salvare l'eventoLiveData
per passare dalla schermata del punteggio a quella di gioco.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgain
- In
ScoreViewModel
, definisci i metodi per impostare e reimpostare l'evento,_eventPlayAgain
.
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}
- In
ScoreFragment
, aggiungi un osservatore pereventPlayAgain
. Inserisci il codice alla fine dionCreateView()
, prima dell'estratto contoreturn
. All'interno dell'espressione lambda, torna alla schermata di gioco e reimpostaeventPlayAgain
.
// 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.
- In
ScoreFragment
, all'interno dionCreateView()
, aggiungi un listener di clic al pulsante PlayAgain e chiamaviewModel
.onPlayAgain()
.
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }
- Esegui l'app e gioca. Al termine della partita, la schermata del punteggio mostra il punteggio finale e il pulsante Gioca di nuovo. Tocca il pulsante PlayAgain e l'app ti reindirizza alla schermata di gioco per poter giocare di nuovo.
Ben fatto! Hai modificato l'architettura della tua app per utilizzare gli oggetti LiveData
in ViewModel
e hai collegato gli osservatori agli oggetti LiveData
. LiveData
notifica gli oggetti osservatori quando cambia il valore contenuto in LiveData
.
Progetto Android Studio: GuessTheWord
LiveData
LiveData
è una classe di contenitore di dati osservabile che riconosce il ciclo di vita, uno dei componenti dell'architettura Android.- Puoi utilizzare
LiveData
per consentire all'interfaccia utente di aggiornarsi automaticamente quando i dati vengono aggiornati. LiveData
è osservabile, il che significa che un osservatore come un'attività o un frammento può ricevere una notifica quando i dati contenuti nell'oggettoLiveData
cambiano.LiveData
contiene dati; è un wrapper che può essere utilizzato con qualsiasi dato.LiveData
è consapevole del ciclo di vita, il che significa che aggiorna solo gli osservatori che si trovano in uno stato del ciclo di vita attivo, ad esempioSTARTED
oRESUMED
.
Per aggiungere LiveData
- Modifica il tipo delle variabili di dati in
ViewModel
inLiveData
oMutableLiveData
.
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 contenuti in
LiveData
, utilizza il metodosetValue()
sulla variabileLiveData
.
Per incapsulare LiveData
LiveData
all'interno diViewModel
deve essere modificabile. Al di fuori diViewModel
,LiveData
deve essere leggibile. Questa operazione può essere implementata 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
LiveData
, utilizzaprivate
MutableLiveData
all'interno diViewModel
e restituisci una proprietà di supportoLiveData
all'esterno diViewModel
.
Observable LiveData
LiveData
segue un pattern di osservazione. L'"osservabile" è l'oggettoLiveData
e gli osservatori sono i metodi nei controller UI, come i fragment. Ogni volta che i dati racchiusi inLiveData
cambiano, i metodi di osservazione nei controller UI vengono notificati.- Per rendere osservabile
LiveData
, collega un oggetto osservatore al riferimentoLiveData
negli osservatori (come attività e frammenti) utilizzando il metodoobserve()
. - Questo pattern dell'observer
LiveData
può essere utilizzato per comunicare daViewModel
ai controller UI.
Corso Udacity:
Documentazione per sviluppatori Android:
Altro:
- Proprietà di supporto in Kotlin
Questa sezione elenca i possibili compiti a casa per gli studenti che seguono questo codelab nell'ambito di un corso guidato da un insegnante. Spetta all'insegnante:
- Assegna i compiti, se richiesto.
- Comunica agli studenti come inviare i compiti.
- Valuta i compiti a casa.
Gli insegnanti possono utilizzare questi suggerimenti nella misura che ritengono opportuna e sono liberi di assegnare qualsiasi altro compito a casa che ritengono appropriato.
Se stai seguendo questo codelab in autonomia, sentiti libero di utilizzare questi compiti per casa per mettere alla prova le tue conoscenze.
Rispondi a queste domande
Domanda 1
Come si incapsula LiveData
memorizzato in un ViewModel
in modo che gli oggetti esterni possano leggere i dati senza poterli aggiornare?
- All'interno dell'oggetto
ViewModel
, modifica il tipo di dati inprivate
LiveData
. Utilizza una proprietà di supporto per esporre i dati di sola lettura di tipoMutableLiveData
. - All'interno dell'oggetto
ViewModel
, modifica il tipo di dati inprivate
MutableLiveData
. Utilizza una proprietà di supporto per esporre i dati di sola lettura di tipoLiveData
. - 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 di tipoLiveData
. - All'interno dell'oggetto
ViewModel
, modifica il tipo di dati inLiveData
. Utilizza una proprietà di supporto per esporre i dati di sola lettura di tipoLiveData
.
Domanda 2
LiveData
aggiorna un controller UI (ad esempio un fragment) se il controller UI si trova in uno dei seguenti stati?
- Ripristinata
- In background
- In pausa
- Arrestata
Domanda 3
Nel pattern observer LiveData
, qual è l'elemento osservabile (cosa viene osservato)?
- Metodo dell'osservatore
- I dati in un oggetto
LiveData
- Il controller UI
- L'oggetto
ViewModel
Inizia la lezione successiva:
Per i link ad altri codelab di questo corso, consulta la pagina di destinazione dei codelab di Android Kotlin Fundamentals.