StateFlow: Hot state-holder til UI
Brug StateFlow som en reaktiv state-container, og observer den i ViewModels.
StateFlow: Hot state-holder til UI er en gratis Kotlin Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Kotlin Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Kotlin Academy-kurset indeholder 4 lektioner i alt.
Hvad er StateFlow?
StateFlow er en varm Flow, der holder tilstand, altid har en værdi og udsender opdateringer til alle indsamlere. Den erstatter LiveData i moderne Kotlin-arkitekturer.
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 sammenlignet med StateFlow
MutableStateFlow er den ændrbare implementering, der bruges internt. Eksponér StateFlow som skrivebeskyttet for eksterne observatører ved at konvertere typen eller bruge .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-- }
}Indsamling af StateFlow
Indsaml StateFlow ligesom enhver anden Flow. Den seneste værdi udsendes straks, når indsamlingen begynder.
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 sammenfatter værdier
StateFlow udsender kun, når værdien ændres. Hvis du angiver den samme værdi to gange, sker der kun én udsendelse — efterfølgende identiske værdier sammenfattes.
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 i ViewModel
Det klassiske ViewModel-mønster: En privat MutableStateFlow ændres af forretningslogikken, mens brugergrænsefladen observerer en offentlig StateFlow.
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() til atomisk ændring
Brug update { } til atomisk at opdatere tilstanden ud fra den aktuelle værdi — det er vigtigt ved samtidige opdateringer.
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 til optimistiske opdateringer
compareAndSet(expect, update) angiver kun den nye værdi, hvis den aktuelle værdi svarer til expect. Det er nyttigt ved optimistisk samtidighed.
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 sammenlignet med LiveData
StateFlow fungerer uden Android-livscyklus. LiveData er opmærksom på livscyklussen, men kan kun bruges med Android. Foretræk StateFlow til delte KMP-ViewModels.
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: Konvertering af kold Flow til StateFlow
flow.stateIn(scope, started, initialValue) konverterer en kold Flow til en varm StateFlow og deler ét abonnement mellem alle indsamlere.
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()
}Strategier for SharingStarted
Eagerly: starter straks. Lazily: starter ved den første indsamler. WhileSubscribed(stopTimeout): stopper, når der ikke er nogen indsamlere, og starter igen, når en abonnerer.
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)Observation af afledt tilstand
Afled en ny StateFlow fra en eksisterende ved hjælp af map + stateIn. Det afledte flow opdateres, hver gang kilden ændres.
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()
}Hurtigt tjek
Hvad gør StateFlow, når du angiver den samme værdi to gange?
Opsamling
StateFlow er en varm Flow, der altid har en værdi og sammenfatter efterfølgende identiske værdier. Brug MutableStateFlow internt, og eksponér StateFlow eksternt. Brug update() til samtidige ændringer og stateIn() til at konvertere kolde flows.
Lær Kotlin med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 51
- Lektioner
- 203
Ofte stillede spørgsmål
Er lektionen “StateFlow: Hot state-holder til UI” gratis?
Ja — alle 3 lektioner i læringssporet Kotlin Academy, inklusive “StateFlow: Hot state-holder til UI”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Kotlin Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “StateFlow: Hot state-holder til UI”?
Brug StateFlow som en reaktiv state-container, og observer den i ViewModels. Du øver dig i Kotlin Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Kotlin Academy?
Der kræves ingen tidligere erfaring. Kotlin Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “StateFlow: Hot state-holder til UI”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Kotlin Academy-lektion?
Ja. Alle Kotlin Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- StateFlow: Hot state-holder til UI
- SharedFlow: Event-busser og engangshændelser
- Konvertering af Cold Flow til Hot med shareIn og stateIn
- Test af StateFlow og SharedFlow med Turbine