skip to content

StateFlow & MutableStateFlow

StateFlow always holds a current value, replays it to new collectors, and skips emissions equal to the previous one. That conflation and deduplication is what makes it the right type for observable UI state and the wrong one for events.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What is StateFlow in Kotlin coroutines, and how does it differ from a plain (cold) Flow?

level: juniorimportance: must knowfreq 80%

answer

  1. Always has .value
  2. Hot, not cold
  3. New collector gets current value first
  4. MutableStateFlow -> asStateFlow() to expose
  5. Idiomatic UI state holder

basics

~10 s

StateFlow is a flow that always holds one current value you can read at any time through .value. A plain Flow holds nothing on its own and only produces values when someone collects it.

solid answer

~40 s

StateFlow<T> is a hot, state-holder Flow from kotlinx.coroutines. It always has a current value exposed by the .value property, so you can read state synchronously without collecting. It is 'hot': the value exists independently of collectors. New collectors immediately receive the current value (replay of 1) and then every subsequent change. By contrast, a cold Flow built with flow { } is inert until collect() runs, re-executes its producer block per collector, and has no .value. StateFlow is read-only; you produce one via MutableStateFlow(initial) and expose it as a StateFlow with asStateFlow(). It is the idiomatic observable-state holder for UI (e.g. ViewModel exposing UI state).

code

kotlin · 4 lines
kotlin
val state = MutableStateFlow("idle")
println(state.value)          // idle, read synchronously
state.value = "loading"        // update
// any collector started now first sees "loading"

go deeper

for a junior

Knows StateFlow holds a current .value and is hot vs a cold flow that needs collection.

for a middle

Explains the private-mutable / public-readonly idiom and replay-of-1 behaviour for new collectors.

for a senior

Contrasts cold-flow per-collector semantics with StateFlow's shared single value and discusses where reading .value vs collecting is appropriate.

for a principal

Frames StateFlow as the observable-state primitive in a unidirectional-data-flow architecture and weighs it against alternatives.

## What StateFlow Is `StateFlow<T>` is an interface in `kotlinx.coroutines.flow`. It is a **hot** flow that models a single, always-present piece of observable state. - **Hot** means the data exists on its own, independent of whether anyone is collecting. A **cold** flow (created with `flow { ... }`) does nothing until a collector calls `collect`, and runs its producer block fresh for each collector. - StateFlow always has a **current value**, readable synchronously via the `.value` property — no coroutine or suspension needed to read it. ## Reading vs collecting Two ways to consume state: - `stateFlow.value` — read the latest value right now, synchronously. - `stateFlow.collect { ... }` — a suspending call that emits the **current** value immediately, then every later change. ## Read-only vs mutable - `StateFlow<T>` is read-only (no way to set the value). - `MutableStateFlow<T>` adds a settable `.value` and `update { }` helpers. The idiom is to keep a private `MutableStateFlow` and expose a public read-only `StateFlow` using `asStateFlow()`. ```kotlin class CounterViewModel { private val _count = MutableStateFlow(0) val count: StateFlow<Int> = _count.asStateFlow() fun increment() { _count.value += 1 } } ``` ## Cold Flow vs StateFlow at a glance - Cold `flow { }`: inert until collected; no `.value`; re-runs per collector. - StateFlow: always live; has `.value`; shares one value among all collectors; new collectors get the current value first. ## Why it matters StateFlow is the standard way to represent screen/UI state because the UI can read the current value synchronously (e.g. on configuration change) and also react to updates.

  • How do you turn a MutableStateFlow into a read-only StateFlow for the public API?
    Call asStateFlow() on it, or declare the public property type as StateFlow<T>; both prevent callers from writing .value.
  • Does a new collector of a StateFlow miss the current value?
    No. StateFlow has replay of 1, so a new collector immediately receives the current value, then subsequent updates.

A cold Flow is a recipe you must cook each time; a StateFlow is a dish always sitting on the counter — anyone walking up sees what's there right now.

saying these in an interview costs you the question

  • Saying StateFlow is cold and only runs when collected
  • Claiming you must collect to read the current value
  • Confusing StateFlow with LiveData semantics in detail
  • Thinking each collector re-runs a producer block like a cold flow
  • Exposing the MutableStateFlow directly as the public type

context

open as a page

Explain conflation and equality-based deduplication in StateFlow. What happens if you set .value to a value equal to the current one?

level: middleimportance: must knowfreq 70%

basics

~10 s

StateFlow only keeps the latest value (conflation) and ignores a new value that equals the current one, so collectors don't get notified of 'changes' to the same value.

open as a page

When updating a MutableStateFlow, why prefer update { } / compareAndSet over reading and reassigning .value? Show a correct pattern.

level: middleimportance: should knowfreq 55%

basics

~10 s

Reading .value then writing it back can lose updates when two threads do it at once. update { } applies your change atomically, so concurrent updates don't clobber each other.

open as a page

When a new collector subscribes to a StateFlow, what does it receive, and how does replay-of-1 interact with conflation for a slow collector?

level: seniorimportance: should knowfreq 50%

basics

~10 s

A new collector immediately gets the current value, then future changes. If the collector is slow, it can skip intermediate values and only sees the latest one each time it's ready.

open as a page

Design-wise, when is StateFlow the right state-holder and when is it a poor fit? Address null handling, the always-present value, and event delivery.

level: principalimportance: nice to knowfreq 35%

basics

~10 s

Use StateFlow when there's always a meaningful current state to read. It's a poor fit for one-time events, because equal values are skipped and intermediate values can be dropped.

open as a page