A shared flow is a hot Kotlin Flow for broadcast-style communication: one emission can reach every collector that is currently subscribed. Unlike a cold flow, collecting it does not start its producer. Emissions may happen with no subscribers present, which suits events or changes that occur independently of any one consumer. section 16.3 section 16.4
Expose read-only broadcasts
Keep the mutable emitter private and publish only a SharedFlow to consumers. A coroutine started on a supplied scope performs the independent production: class RadioStation { private val _messageFlow = MutableSharedFlow<Int>() val messageFlow = _messageFlow.asSharedFlow() fun beginBroadcasting(scope: CoroutineScope) { scope.launch { while (true) { delay(500.milliseconds) _messageFlow.emit(Random.nextInt(0..10)) } } } } Collectors call messageFlow.collect { ... }, but cannot emit. This split makes the owner of the stream responsible for publishing values while other code only subscribes. section 16.3.1
Figure 16.5 Shared flows operate in a broadcast fashion. When an element is emitted into the shared flow, all subscribers currently collecting the flow will receive this emission.
Each emitted value is delivered to all subscribers collecting at that moment; a later subscriber begins with later emissions unless replay is configured. section 16.3.1
Subscription time matters. With the default configuration, values emitted before a collector starts are not delivered to that collector. Configure a replay cache when late subscribers need a limited number of earlier values, for example MutableSharedFlow<Int>(replay = 5). Replay changes what newcomers can receive; it does not make a shared flow a history-oriented state holder. section 16.3.1 section 16.3.3
Use shared flow when the thing being communicated is an event broadcast and subscribers may come and go. For state, prefer StateFlow when possible: it represents one value, emits on actual changes through equality-based conflation, and can instead hold accumulated history for collectors that arrive later. A shared flow requires deliberate coordination when subscribers must not miss an emission. section 16.3.3
A cold flow can be converted into a hot shared flow with shareIn. This is useful when one producer, such as a temperature query stream, should feed several collectors rather than rerunning the cold-flow logic separately for each one. Cold flows remain the usual choice for services such as network requests or database reads. section 16.3.1 section 16.3.4
Practical checks before choosing a shared flow:
- Start and own an emission coroutine; constructing MutableSharedFlow alone does not produce values. section 16.3.1
- Expose asSharedFlow() rather than the mutable flow when consumers should only collect. section 16.3.1
- Decide whether missed events are acceptable; use replay deliberately or model durable information as state. section 16.3.1 section 16.3.3
