La versione Kotlin delle API Home utilizza i flussi, una funzionalità del linguaggio Kotlin che offre potenti funzionalità per la gestione di stream di dati asincroni, tra cui trasformazione, filtri, mappatura, conversione da e verso raccolte e così via.
Le routine di co-routine sono strettamente associate ai flussi e forniscono un'astrazione elegante per scrivere codice asincrono e liberano lo sviluppatore dall'obbligo di scrivere esplicitamente le routine di callback. I flussi funzionano in sinergia con le coroutine e consentono di recuperare i dati dalle coroutine in modo asincrono, senza dover attendere il completamento di una funzione o di un thread.
I dati vengono recuperati da un flusso dal consumatore in un processo chiamato raccolta.
I flussi Kotlin hanno una funzione collect()
che può essere utilizzata per questo scopo. Che cosa accade in un flusso durante la raccolta dipende dal tipo di flusso.
I flussi Kotlin (Flow<T>
) sono freddi per impostazione predefinita, il che significa che il codice del generatore di flussi produce dati solo quando viene chiamato collect()
. Un flusso hot, invece, produce immediatamente i dati, memorizzali in un buffer in memoria come una coda per ogni volta che vengono utilizzati. Poiché mantiene i dati in memoria, un flusso caldo è considerato stateful.
I flussi possono essere convertiti da freddi a caldi utilizzando l'operatore shareIn
(consulta Creare flussi caldi utilizzando
shareIn
). Puoi anche utilizzare SharedFlow
o StateFlow
per trasformare un flusso freddo in un
flusso caldo.
Come l'app di esempio utilizza i flussi
L'app di esempio utilizza i modelli di visualizzazione in Jetpack Compose collegati ai flussi nelle API Home. Molti elementi dell'interfaccia utente dell'app di esempio sono basati sullo stato, ma è possibile interagire con essi. L'app di esempio combina anche lo stato dei dispositivi con uno stato "ottimista" nell'UI per un'esperienza utente in tempo reale. Il termine ottimistico indica che l'app presuppone che un'azione sia riuscita e aggiorna immediatamente l'interfaccia utente in modo da riflettere il risultato previsto senza attendere la conferma. Se risulta che l'azione non è riuscita, l'interfaccia utente viene aggiornata in modo da riflettere lo stato reale.
Nell'app di esempio, i flussi vengono creati per ogni livello del modello di visualizzazione (strutture, camere, dispositivi). Ad esempio, lo fa per le strutture con la seguente chiamata in GlobalViewModel.kt
:
fun getStructuresState(): StateFlow<List<StructureModel>?> =
homeClient
.structures()
.map { structures -> structures.map { StructureModel(it.name, it) }.sortedBy { it.name } }
.handleErrors()
.flowOn(Dispatchers.IO)
.stateIn(scope = viewModelScope, started = SharingStarted.WhileSubscribed(), null)
emitAll()
raccoglie tutti i valori dal flusso specificato e li emette al raccoltore. stateIn()
condivide il valore emesso più di recente da una singola istanza in esecuzione del flusso a monte con più iscritti a valle. Per ulteriori informazioni, consulta la documentazione di riferimento kotlinx.coroutines.flow
.
Jetpack Compose
Per archiviare gli oggetti del flusso nella memoria locale e impedirne l'interruzione,
utilizza l'API Kotlin
remember
.
In Jetpack Compose, se lo utilizzi con
collectAsStateWithLifecycle()
,
Jetpack gestisce automaticamente l'iscrizione e la disattivazione dei flussi in base al fatto che
l'interfaccia utente dell'applicazione che mostra lo stato sia effettivamente in primo piano o
no.
Una semplice chiamata nell'app di esempio esegue questa operazione. Utilizzando la funzione getStructuresState()
mostrata in precedenza:
val structuresList by
remember(globalViewModel) { globalViewModel.getStructuresState() }.collectAsStateWithLifecycle()
Ora, quando uno stato della struttura cambia (ad esempio name
), la funzione Composable che lo utilizza rifletterà automaticamente lo stato aggiornato.
Nell'app di esempio, si tratta della funzione HomeActivityContent()
.
Risorse
Per saperne di più su Kotlin, sui flussi, sulle coroutine e su Jetpack Compose, consulta le seguenti risorse:
- Sviluppare app per Android con Kotlin
- Imparare Kotlin per Android
- Coroutine Kotlin su Android. Potrebbero essere utili questi codelab specifici:
- Kotlin Flow su Android e, più specificamente, su StateFlow.
- Stato e Jetpack Compose, in particolare la funzione
collectAsStateWithLifecycle()
. Questa funzione gestisce automaticamente l'iscrizione e la disiscrizione ai flussi in base al fatto che l'interfaccia utente che mostra lo stato sia effettivamente in primo piano o meno. - Se utilizzi l'API Automation, ti consigliamo di leggere l'articolo sui costruttori sicuri di tipo Kotlin per comprendere il funzionamento del DSL di automazione.