flowOn
- Kotlin course
- Intermediate
- Lesson 92/116
- 5 min
Learn context switching with flowOn.
flowOn: Changing context
flowOn(dispatcher) sets the coroutine context for the upstream of the flow. Upstream means the builder and intermediate operators before flowOn. collect keeps running in the caller's context.
fun numbers(): Flow<Int> = flow {
for (i in 1..3) emit(i)
}
fun main() = runBlocking {
numbers()
.flowOn(Dispatchers.IO)
.collect { println(it) }
}Dispatchers.IO is recommended for file/network I/O, Dispatchers.Default for CPU work. The order of values is preserved; only the thread that runs emit changes.
The upstream concept
The position of flowOn matters: it only affects the part before it. So the builder (flow { }) and intermediate operators (map, filter) run in the specified context. collect stays in the caller's context.
numbers()
.map { it * 2 } // in flowOn context
.flowOn(Dispatchers.Default)
.collect { println(it) } // in runBlocking contextThe order and content of values are preserved; you only move where the computation happens. This is useful to keep slow work such as network calls or file reads off the UI thread.
Practice Set the context with flowOn
Define fun numbers(): Flow<Int> = flow { ... }. In the body use a for (i in 1..3) loop with emit(i). Mark main with runBlocking. Inside it call numbers().flowOn(Dispatchers.IO).collect { println(it) }. The output prints each value on its own line.
Starter code
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
// numbers function: inside flow { } emit 1, 2, 3
// main: apply the IO dispatcher to numbers, collect and print
fun main() = runBlocking {
// write here
}Sample solution
fun numbers(): Flow<Int> = flow {
for (i in 1..3) {
emit(i)
}
}
fun main() = runBlocking {
numbers().flowOn(Dispatchers.IO).collect { println(it) }
}Expected output
1 2 3
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Change the context
numbers().____(Dispatchers.IO).collect { println(it) }
numbers().flowOn(Dispatchers.IO).collect { println(it) }
Explanation: flowOn sets the context for the upstream.
2 What does flow.flowOn(Dispatchers.IO) change?
- The value type of the flow
- The context of the collect call
- The context the upstream of the flow runs on Correct answer
- The cold nature of the flow
Explanation: flowOn sets the context for the upstream (builder and intermediate operators).
3 Match context and dispatcher
| Term | Meaning |
|---|---|
flowOn |
Sets context |
Dispatchers.IO |
I/O work |
Dispatchers.Default |
CPU work |
upstream |
Above the call |