When would you choose SharedFlow over StateFlow? Give concrete scenarios and the trade-offs.
answer
- StateFlow = state (1 current value, conflated, dedup)
- SharedFlow = events (replay=0, no conflation, no dedup)
- Events in StateFlow => conflation + replay bugs
- StateFlow IS a SharedFlow (replay=1 + conflate)
- Snackbar/nav => SharedFlow
basics
~10 sUse StateFlow for a current value (state) that the UI reads. Use SharedFlow for one-off events like navigation or toasts, where there's no meaningful current value and you don't want conflation or re-delivery.
solid answer
~40 sStateFlow models state: it always has exactly one current value, requires an initial value, conflates rapid updates (only the latest survives), and skips emitting equal consecutive values (distinctUntilChanged). New collectors immediately get the current value. SharedFlow models events: no initial value, configurable replay (default 0, so new collectors see nothing past), no conflation by default, no equality filtering, and a tunable buffer/overflow policy. Choose SharedFlow for one-shot events — navigation commands, snackbars, vibration, analytics — where conflation would lose events and re-delivering on resubscribe (StateFlow's behaviour) would replay stale events. Choose StateFlow for screen state, settings, connectivity flags. StateFlow is actually a specialized SharedFlow with replay=1, conflation, and equality-based deduplication baked in. The classic pitfall is using StateFlow for events: conflation drops bursts and resubscription replays the last event.
go deeper
Knows StateFlow = state with a current value, SharedFlow = events.
Lists conflation, equality dedup, and replay differences and picks correctly for snackbar vs screen state.
Explains the event anti-pattern (conflation + resubscribe replay) and that StateFlow is a specialized SharedFlow, choosing with trade-offs.
Sets a team convention for state-vs-event flows, weighs lossless event delivery alternatives (Channel) and the lifecycle/resubscription semantics across the app.
## The mental model - **StateFlow = state**: one current value, always available. - **SharedFlow = events**: a stream of occurrences, no "current" concept by default. ## What StateFlow gives you - **Initial value required**: `MutableStateFlow(initial)`. - **replay = 1, conflated**: only the latest value is kept; fast successive updates can collapse so a slow collector may skip intermediate values. - **Equality-based dedup**: emitting a value `equal` to the current one is a no-op (`distinctUntilChanged` semantics). Define `equals` correctly or updates silently vanish. - New subscribers immediately receive the current value. ## What SharedFlow gives you - **No initial value**, `replay` default `0`. - **No conflation** unless you configure DROP_OLDEST overflow; values are buffered/delivered in order. - **No equality filtering**: two equal events both fire. - Tunable `replay`, `extraBufferCapacity`, `onBufferOverflow`. ## Concrete choices | Need | Use | |------|-----| | Current UI screen state | StateFlow | | Connectivity / toggle flags | StateFlow | | Navigate-to-screen command | SharedFlow (replay=0) | | Show snackbar / toast | SharedFlow | | Analytics / one-shot signals | SharedFlow | ## Why not StateFlow for events Two same-text snackbar requests would be deduped by equality (second never fires). A burst of events can be conflated to just the last. And because StateFlow replays its latest value, a config change / resubscription **re-shows** the last event. SharedFlow with `replay=0` avoids all three. ```kotlin // Events: one-shot, not conflated, not re-delivered private val _nav = MutableSharedFlow<NavCommand>() val nav: SharedFlow<NavCommand> = _nav.asSharedFlow() // State: always-current value private val _ui = MutableStateFlow(UiState.Loading) val ui: StateFlow<UiState> = _ui.asStateFlow() ``` ## Relationship `StateFlow` **is** a `SharedFlow` (interface inheritance): a SharedFlow specialized to replay=1, conflation, and equality dedup. So everything you know about SharedFlow buffering underlies StateFlow.
- Why is StateFlow a bad fit for showing the same toast twice in a row?StateFlow dedups by equality, so the second identical value is a no-op and the toast never re-shows.
- Can SharedFlow emulate StateFlow?Roughly: MutableSharedFlow(replay=1, onBufferOverflow=DROP_OLDEST) gives latest-value replay, but it lacks StateFlow's equality dedup, the value property, and the initial-value guarantee.
StateFlow is a whiteboard always showing the latest figure; SharedFlow is a PA system announcing each event once as it happens.
saying these in an interview costs you the question
- Using StateFlow for one-shot events without acknowledging conflation/replay bugs
- Saying StateFlow and SharedFlow are unrelated types
- Claiming SharedFlow conflates by default
- Not knowing StateFlow requires an initial value