Why didn't my StateFlow update?

Flow and StateFlow Mid-level Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Spot the bug

Tapping Add doesn't update the list on screen. Which line is the bug?

  1. class CartViewModel : ViewModel() {
  2. private val items = mutableListOf<String>()
  3. val state = MutableStateFlow<List<String>>(items)
  4. ​
  5. fun add(item: String) {
  6. items.add(item)
  7. state.value = items
  8. }
  9. }
Hint 1 of 1

Is the new value a different list from the old one?

Choose an answer, then open Show answer below to check it.

Show answer
  • Answer: line 7 state.value = items

The same list object is assigned back, so the new value equals the old one and StateFlow emits nothing. Use state.update { it + item } with an immutable list.

30-second answer

StateFlow only emits when the new value is not equal to the old one. If you mutate a MutableList in place and assign the same list back, the old and new values are the same object, so nothing is emitted. Hold immutable data and replace it with a copy: state.update { it.copy(items = it.items + item) }.

Practise saying it · 30 s. No recording, just a timer

Explain why a StateFlow might not emit.

Say your answer out loud, then check which of these points you covered:

  • It skips equal values
  • Mutating in place gives the same object
  • Use immutable data and copy
  • update is atomic

Deep dive

Data class equals compares properties, so a copy with the same values is also skipped, which is usually what you want.

Compose has the same rule: mutating a list inside mutableStateOf doesn't trigger recomposition.

Use List, not MutableList, in state classes, so mutation in place can't compile.

update { } is atomic, which also fixes lost updates from several coroutines.

Common mistakes

  • Mutating a list in place and reassigning it.
  • Using MutableList inside UI state.
  • Trying to force an emit by creating a new StateFlow.

Senior take & follow-ups

Connect it to immutability as a design rule, not just a StateFlow quirk.

Follow-up questions

Think of your answer first, then open the hint.

  1. How does this relate to Compose stability?

    Show hint

    Immutable state lets Compose skip unchanged parts safely.

  2. Does StateFlow compare with == or ===?

    Show hint

    With equals (==).

Suggest a fix if something here is wrong or out of date.