StateFlow: contenitore hot dello stato per l'interfaccia
Utilizzi StateFlow come contenitore reattivo dello stato e lo osservi nei ViewModel.
StateFlow: contenitore hot dello stato per l'interfaccia è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.
Che cos'è StateFlow?
StateFlow è un Flow hot che mantiene lo stato, ha sempre un valore ed emette gli aggiornamenti a tutti i collector. Sostituisce LiveData nelle moderne architetture Kotlin.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val stateFlow = MutableStateFlow(0) // initial value
println("Current: ${stateFlow.value}")
stateFlow.value = 42
println("Updated: ${stateFlow.value}")
}MutableStateFlow rispetto a StateFlow
MutableStateFlow è l'implementazione modificabile usata internamente. Esponga StateFlow (in sola lettura) agli osservatori esterni tramite cast o usando .asStateFlow().
import kotlinx.coroutines.flow.*
class CounterViewModel {
private val _count = MutableStateFlow(0) // mutable internally
val count: StateFlow<Int> = _count.asStateFlow() // read-only externally
fun increment() { _count.value++ }
fun decrement() { _count.value-- }
}Raccolta di StateFlow
Raccolga StateFlow come qualsiasi altro Flow. L'ultimo valore viene emesso immediatamente quando inizia la raccolta.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val state = MutableStateFlow("loading")
launch {
state.collect { println("State: $it") }
}
delay(50); state.value = "success"
delay(50); state.value = "idle"
delay(50)
coroutineContext.cancelChildren()
}StateFlow accorpa i valori
StateFlow emette valori solo quando il valore cambia. Se si imposta due volte lo stesso valore, si verifica una sola emissione: i valori consecutivi duplicati vengono accorpati.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val flow = MutableStateFlow("A")
launch {
flow.collect { println("Received: $it") }
}
delay(50)
flow.value = "A" // no emission — same value
flow.value = "B" // emits
flow.value = "B" // no emission — same value
flow.value = "C" // emits
delay(50)
coroutineContext.cancelChildren()
}StateFlow nel ViewModel
Il modello canonico per un ViewModel: un MutableStateFlow privato modificato dalla logica di business e un StateFlow pubblico osservato dall'interfaccia utente.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
sealed class UiState { object Loading : UiState(); data class Success(val data: String) : UiState(); data class Error(val msg: String) : UiState() }
class MyViewModel(scope: CoroutineScope) {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
init {
scope.launch {
delay(100) // simulate load
_uiState.value = UiState.Success("Hello!")
}
}
}update() per una modifica atomica
Utilizzi update { } per aggiornare lo stato in modo atomico sulla base del valore corrente, un aspetto importante per gli aggiornamenti concorrenti.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val counter = MutableStateFlow(0)
List(100) {
launch(Dispatchers.Default) {
counter.update { it + 1 } // thread-safe atomic update
}
}.forEach { it.join() }
println("Counter: ${counter.value}") // 100
}compareAndSet per gli aggiornamenti ottimistici
compareAndSet(expect, update) imposta il nuovo valore solo se quello corrente corrisponde a expect. È utile per la concorrenza ottimistica.
import kotlinx.coroutines.flow.*
fun main() {
val state = MutableStateFlow("idle")
val changed = state.compareAndSet("idle", "loading")
println("Changed: $changed, Value: ${state.value}") // true, loading
val changed2 = state.compareAndSet("idle", "error") // won't change
println("Changed: $changed2, Value: ${state.value}") // false, loading
}StateFlow rispetto a LiveData
StateFlow funziona senza il ciclo di vita di Android. LiveData tiene conto del ciclo di vita, ma funziona solo su Android. Preferisca StateFlow per i ViewModel KMP condivisi.
import kotlinx.coroutines.flow.*
// StateFlow: pure Kotlin, works in commonMain
// val state = MutableStateFlow("value")
// LiveData: Android-only, lifecycle-aware
// val liveData = MutableLiveData("value")
// In Compose, collect StateFlow with:
// val state by viewModel.uiState.collectAsState()
fun main() { println("StateFlow: multiplatform; LiveData: Android-only") }stateIn: conversione di un Flow freddo in StateFlow
flow.stateIn(scope, started, initialValue) converte un Flow freddo in uno StateFlow hot, condividendo una sola sottoscrizione tra tutti i collector.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val cold = flow {
println("Fetching...")
delay(100)
emit("data")
}
val hot: StateFlow<String> = cold.stateIn(
scope = this,
started = SharingStarted.Lazily,
initialValue = "loading"
)
launch { hot.collect { println("A: $it") } }
launch { hot.collect { println("B: $it") } }
delay(200)
coroutineContext.cancelChildren()
}Strategie SharingStarted
Eagerly: avvia immediatamente. Lazily: avvia al primo collector. WhileSubscribed(stopTimeout): si arresta quando non ci sono collector e riparte quando uno si sottoscrive.
import kotlinx.coroutines.flow.*
// Eagerly: upstream starts right away
// SharingStarted.Eagerly
// Lazily: waits for first subscriber
// SharingStarted.Lazily
// WhileSubscribed: stops 5s after last subscriber
// SharingStarted.WhileSubscribed(5000)
// Typical ViewModel usage:
// val uiState = repo.dataFlow.stateIn(viewModelScope, WhileSubscribed(5000), Loading)Osservazione dello stato derivato
Derivi un nuovo StateFlow da uno esistente usando map + stateIn. Il flow derivato si aggiorna ogni volta che cambia la sorgente.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val count = MutableStateFlow(5)
val doubled = count.map { it * 2 }.stateIn(this, SharingStarted.Eagerly, 10)
println(doubled.value) // 10
count.value = 7
delay(50)
println(doubled.value) // 14
coroutineContext.cancelChildren()
}Verifica rapida
Che cosa fa StateFlow quando si imposta due volte lo stesso valore?
Riepilogo
StateFlow è un Flow hot, che ha sempre un valore e accorpa i valori duplicati. Utilizzi MutableStateFlow internamente ed esponga StateFlow esternamente. Utilizzi update() per le modifiche concorrenti e stateIn() per convertire i flow freddi.
Impara Kotlin con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 51
- Lezioni
- 203
Domande Frequenti
La lezione «StateFlow: contenitore hot dello stato per l'interfaccia» è gratuita?
Sì — il testo completo di «StateFlow: contenitore hot dello stato per l'interfaccia» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.
Cosa imparerò in «StateFlow: contenitore hot dello stato per l'interfaccia»?
Utilizzi StateFlow come contenitore reattivo dello stato e lo osservi nei ViewModel. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Kotlin Academy?
Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «StateFlow: contenitore hot dello stato per l'interfaccia»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?
Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- StateFlow: contenitore hot dello stato per l'interfaccia
- SharedFlow: event bus ed eventi one-shot
- Convertire un Flow cold in hot con shareIn e stateIn
- Testare StateFlow e SharedFlow con Turbine