What is StateFlow in Kotlin coroutines, and how does it differ from a plain (cold) Flow?
answer
- Always has .value
- Hot, not cold
- New collector gets current value first
- MutableStateFlow -> asStateFlow() to expose
- Idiomatic UI state holder
basics
~10 sStateFlow 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 sStateFlow<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 linesval state = MutableStateFlow("idle")
println(state.value) // idle, read synchronously
state.value = "loading" // update
// any collector started now first sees "loading"go deeper
Knows StateFlow holds a current .value and is hot vs a cold flow that needs collection.
Explains the private-mutable / public-readonly idiom and replay-of-1 behaviour for new collectors.
Contrasts cold-flow per-collector semantics with StateFlow's shared single value and discusses where reading .value vs collecting is appropriate.
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