StateFlow & SharedFlow Flashcards
KOTLIN › Concurrency
- What does it mean that StateFlow and SharedFlow are hot flows?
- They stay active and hold their state in memory independently of collectors. Collecting does not trigger producer code, and the same emissions are shared across all collectors, unlike a cold flow{} which restarts its producer per collector.
- Why does StateFlow require an initial value while SharedFlow does not?
- StateFlow is a state holder that must always expose a current value via .value, so it needs a seed. SharedFlow models events and holds no current state, so an initial value would be meaningless; by default it has replay = 0.
- What is conflation in StateFlow, and what surprising consequence does it have?
- StateFlow only emits when the new value differs (equals-based, like distinctUntilChanged), and fast intermediate updates may be skipped so collectors only see the latest. Setting .value to a value equal to the current one emits nothing.
- When should you use SharedFlow instead of StateFlow?
- For one-off events that must not be replayed or conflated: navigation commands, snackbars, toasts, one-shot dialogs. StateFlow would re-deliver its latest value to new collectors (e.g. after rotation), causing the event to fire again.
- What do replay, extraBufferCapacity, and onBufferOverflow control in MutableSharedFlow?
- replay = how many past values new collectors receive. extraBufferCapacity = buffer slots beyond replay for slow collectors. onBufferOverflow = policy when full: SUSPEND (default), DROP_OLDEST, or DROP_LATEST.
- What is the difference between emit and tryEmit on MutableSharedFlow?
- emit is a suspend function that suspends the caller when the buffer is full (with SUSPEND policy). tryEmit is non-suspending and returns Boolean: it succeeds only if there is buffer space or a drop policy applies, otherwise returns false.
- Why is repeatOnLifecycle(STARTED) the recommended way to collect a flow in a View/Activity?
- It starts collection when the lifecycle reaches STARTED and cancels the whole coroutine at STOPPED, fully tearing down the upstream producer when the UI is not visible, then restarts it on return. It avoids both crashes and wasted background work.
- Why are launchWhenStarted and launchWhenResumed discouraged?
- They only suspend the coroutine below the target state instead of cancelling it, so the upstream flow producer stays active and wastes resources while the UI is hidden. They are deprecated in favor of repeatOnLifecycle / collectAsStateWithLifecycle.
- What does .stateIn(scope, SharingStarted.WhileSubscribed(5000), initialValue) give you?
- It converts a cold flow into a hot StateFlow scoped to (typically) viewModelScope. WhileSubscribed(5000) keeps the upstream alive for 5s after the last collector leaves, so it survives configuration changes without restarting the producer on quick rotations.