Flow: the Basics Quiz
KOTLIN › Concurrency
What best describes a Kotlin Flow?
- A suspend function that returns a single value
- An asynchronous stream of values that arrive over time
- A thread pool for background work
- A replacement for a plain variable
Answer: An asynchronous stream of values that arrive over time
A Flow models a stream of multiple values over time (updates, rows, results), unlike a suspend function that returns one value once.
Inside a flow { } builder, how do you hand a value to the collector?
- return value
- emit(value)
- yield(value)
- collect(value)
Answer: emit(value)
emit(value) sends a value from the producer to the collector, one at a time.
You write val f = flow { println("hi"); emit(1) } and never collect it. What happens?
- "hi" prints immediately
- Nothing runs, a flow is lazy until a terminal operator collects it
- It throws at runtime
- 1 is emitted to a default collector
Answer: Nothing runs, a flow is lazy until a terminal operator collects it
Flows are cold and lazy: creating one only describes the stream. The producer runs only when a terminal operator like collect starts it.
Why must collect be called from inside a coroutine?
- It's a blocking call
- collect is a suspend function
- Flows always use Dispatchers.IO
- To avoid memory leaks
Answer: collect is a suspend function
collect is a suspend function, so it can only be called from a coroutine or another suspend function.
Two separate coroutines each collect the same cold flow. How many times does the producer block run?
- Once, shared between them
- Twice, once independently per collector
- Zero times
- It depends on timing
Answer: Twice, once independently per collector
A cold flow re-runs its producer independently for every collector; nothing is shared by default.
Which is a genuine advantage of Flow over callback/listener APIs?
- It runs faster on all devices
- You write straight-line suspending code and get cancellation for free
- It never throws exceptions
- It doesn't need a coroutine
Answer: You write straight-line suspending code and get cancellation for free
The flow builder is a suspending context, so you call suspend functions inline (no callbacks), and collection is cancellable with the coroutine.
What can you legally do inside a flow { } block?
- Only emit constant values
- Call suspend functions like delay() or a network call, then emit their results
- Start new threads manually and forget them
- Return a List directly instead of emitting
Answer: Call suspend functions like delay() or a network call, then emit their results
The flow builder is a suspending context, so you can call any suspend function and emit the results, which is what makes Flow so ergonomic.
Which of these is a terminal operator that starts the flow running?
- map
- filter
- collect
- onEach
Answer: collect
collect (like toList/first) is terminal, it actually drives the flow. map/filter/onEach are lazy intermediate operators that run nothing by themselves.
A cold flow is best described as…
- Always running and shared across collectors
- Runs on demand when collected, independently per collector
- Cached after the first collection
- Collectable only once
Answer: Runs on demand when collected, independently per collector
Cold = nothing runs until collected, and each collector triggers its own fresh run. The opposite is a hot flow (always-on, shared).
You need a value that changes over time and is observed by the UI (e.g. current search results). Which shape fits?
- A regular suspend fun returning the value once
- A Flow that emits new results as they change
- A blocking while loop on the main thread
- A global variable polled every frame
Answer: A Flow that emits new results as they change
Values that change over time and are observed are exactly what a Flow (a stream) models; a single suspend return only gives you one snapshot.