Kotlin concurrency
Kotlin Coroutines and Flow Interview Guide
Explain coroutine ownership and stream semantics in terms of the user-visible system.
Short answer
What matters most
For Kotlin coroutine interviews, explain who owns each coroutine, which scope defines its lifetime, how cancellation propagates and which dispatcher matches the work. Structured concurrency keeps child work attached to a meaningful parent. Flow is cold by default, while StateFlow and SharedFlow model different hot-stream behaviors. A senior answer distinguishes transient events from durable state, explains replay and buffering, and avoids collecting the same expensive upstream work repeatedly. Connect the concepts to lifecycle-aware collection, stale requests, retry policy, offline queues and test dispatchers. The goal is not to recite operators. It is to prove that concurrent work ends when it should and the UI cannot display an impossible state.
Trace ownership first
For every launch, identify the parent scope and the product event that should cancel it. Global work requires an explicit application-level owner, not GlobalScope.
- Parent and child lifetime
- Cancellation propagation
- Exception supervision
- Dispatcher choice
- Shared upstream work
- Deterministic tests
StateFlow, SharedFlow and channels
StateFlow represents a current value. SharedFlow broadcasts values with configurable replay and buffering. Channels coordinate producers and consumers. Choose based on semantics, not fashion.
A navigation event is not automatically a stream. Ask whether the event must survive a collector disappearing and how duplicate handling works.
Interview failure cases
Practice duplicate collectors, a retry loop after cancellation, blocking work on Main, a swallowed exception and an old request overwriting new state.
For each, explain how a test would force the bad ordering instead of hoping the race happens.