Collection starts a cold flow
A flow built with flow { ... } is cold: its producer runs for each collection. Hot streams such as StateFlow and SharedFlow have lifetimes independent of an individual collector. This example requires kotlinx-coroutines-core.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
var starts = 0
val values = flow {
starts++
emit(25)
}
check(values.first() == 25)
check(values.first() == 25)
check(starts == 2)
}
Two collectors can therefore trigger two network requests if the producer performs one. Sharing with shareIn or stateIn requires a scope and a deliberate start/stop policy. StateFlow retains a current value and conflates equal updates; it is not a guaranteed log of every intermediate event.
Exercise
Add a transformation to double the emitted value and confirm the producer still starts twice. Sketch which scope should own shared screen state in an Android app.
Check: distinguish a stream's lifetime from the lifetime of any one UI collector.