Intermediate 8 min readKotlin 2.0
Kotlin StateFlow — Observable State for UI
StateFlow is a hot flow that always holds the latest value and emits it to all new collectors. It is ideal for UI state in ViewModels.
What You Will Learn
- Create MutableStateFlow
- Read and update state
- Collect StateFlow values
- Compare StateFlow with LiveData
- Use StateFlow in a ViewModel pattern
MutableStateFlow
MutableStateFlow holds a value and broadcasts changes to all collectors.
Basic StateFlow
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val counter = MutableStateFlow(0)
val job = launch {
counter.collect { println("Count: $it") }
}
delay(100)
counter.value = 1
delay(100)
counter.value = 2
delay(100)
counter.value = 3
delay(100)
job.cancel()
}Output
Count: 0
Count: 1
Count: 2
Count: 3
MutableStateFlow(0) creates a flow with initial value 0. Setting .value = x emits the new value to all collectors. The collector in launch receives each update.
Best Practice: Expose StateFlow as a read-only StateFlow from your ViewModel: private val _state = MutableStateFlow(...); val state: StateFlow<T> = _state.asStateFlow()
StateFlow in a ViewModel Pattern
Use StateFlow to model UI state.
ViewModel Pattern
kotlin
import kotlinx.coroutines.flow.*
data class UiState(val count: Int = 0, val loading: Boolean = false)
class CounterViewModel {
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
fun increment() {
_uiState.value = _uiState.value.copy(count = _uiState.value.count + 1)
}
fun decrement() {
_uiState.value = _uiState.value.copy(count = _uiState.value.count - 1)
}
}
fun main() {
val vm = CounterViewModel()
vm.increment()
vm.increment()
vm.decrement()
println(vm.uiState.value)
}Output
UiState(count=1, loading=false)
UiState is a data class. .copy() creates a new UiState with only the changed properties. _uiState is private (mutable). uiState is public (read-only). This is the standard Android ViewModel pattern.
Practice Exercise
Exercisemultiple choice
What value does a new StateFlow collector receive immediately upon subscribing?
Quick Quiz
Quick Quiz
How do you expose StateFlow as read-only from a ViewModel?
Frequently Asked Questions
Related Tutorials
Last updated: 2026-05-01Kotlin 2.0
Written by KotlinGuide Editorial Team · Reviewed by KotlinGuide Technical Review