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