StateFlow: reaktiver Zustandscontainer für die UI
Verwenden Sie StateFlow als reaktiven Zustandscontainer und beobachten Sie ihn in ViewModels.
StateFlow: reaktiver Zustandscontainer für die UI ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.
Was ist StateFlow?
StateFlow ist ein heißer, zustandshaltender Flow, der immer einen Wert besitzt und Aktualisierungen an alle Collector sendet. In modernen Kotlin-Architekturen ersetzt er LiveData.
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 im Vergleich zu StateFlow
MutableStateFlow ist die intern verwendete veränderbare Implementierung. Stellen Sie externen Beobachtern einen schreibgeschützten StateFlow bereit, indem Sie ihn casten oder .asStateFlow() verwenden.
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-- }
}StateFlow sammeln
Sammeln Sie StateFlow wie jeden anderen Flow. Der aktuelle Wert wird beim Sammeln sofort ausgegeben.
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 ist konfluiert
StateFlow gibt nur Werte aus, wenn sich der Wert ändert. Wenn Sie denselben Wert zweimal setzen, wird nur eine Ausgabe erzeugt – aufeinanderfolgende doppelte Werte werden zusammengefasst.
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 im ViewModel
Das kanonische ViewModel-Muster: Ein privater MutableStateFlow wird von der Geschäftslogik verändert, ein öffentlicher StateFlow von der UI beobachtet.
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() für atomare Änderungen
Verwenden Sie update { }, um den Zustand atomar auf Grundlage des aktuellen Werts zu aktualisieren – das ist für nebenläufige Aktualisierungen wichtig.
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 für optimistische Aktualisierungen
compareAndSet(expect, update) setzt den neuen Wert nur, wenn der aktuelle Wert mit expect übereinstimmt. Das ist für optimistische Nebenläufigkeit nützlich.
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 im Vergleich zu LiveData
StateFlow funktioniert ohne den Android-Lebenszyklus. LiveData berücksichtigt den Lebenszyklus, ist aber auf Android beschränkt. Bevorzugen Sie StateFlow für gemeinsam genutzte 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: Cold Flow in StateFlow umwandeln
flow.stateIn(scope, started, initialValue) wandelt einen kalten Flow in einen heißen StateFlow um und teilt ein Abonnement unter allen Collectors.
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()
}Strategien für SharingStarted
Eagerly: startet sofort. Lazily: startet beim ersten Collector. WhileSubscribed(stopTimeout): stoppt, wenn keine Collector vorhanden sind, und startet neu, sobald einer abonniert.
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)Abgeleiteten Zustand beobachten
Leiten Sie mit map + stateIn einen neuen StateFlow aus einem vorhandenen ab. Der abgeleitete Flow wird aktualisiert, sobald sich die Quelle ändert.
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()
}Kurze Überprüfung
Was tut StateFlow, wenn Sie denselben Wert zweimal setzen?
Zusammenfassung
StateFlow ist ein heißer, immer mit einem Wert versehener und konfluierter Flow. Verwenden Sie intern MutableStateFlow und stellen Sie extern StateFlow bereit. Verwenden Sie update() für nebenläufige Änderungen und stateIn(), um kalte Flows umzuwandeln.
Lerne Kotlin mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 51
- Lektionen
- 203
Häufig gestellte Fragen
Ist die Lektion „StateFlow: reaktiver Zustandscontainer für die UI“ kostenlos?
Ja — der vollständige Text von „StateFlow: reaktiver Zustandscontainer für die UI“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „StateFlow: reaktiver Zustandscontainer für die UI“?
Verwenden Sie StateFlow als reaktiven Zustandscontainer und beobachten Sie ihn in ViewModels. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Kotlin Academy zu starten?
Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „StateFlow: reaktiver Zustandscontainer für die UI“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?
Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- StateFlow: reaktiver Zustandscontainer für die UI
- SharedFlow: Event-Busse und einmalige Events
- Cold Flow mit shareIn und stateIn in Hot Flow umwandeln
- StateFlow und SharedFlow mit Turbine testen