How to Use flowOn in Kotlin for Coroutine Context Switching
Use
flowOn in Kotlin to change the coroutine context where a Flow is executed, typically to switch to a background thread for heavy work. It is applied to a flow to specify the dispatcher, like Dispatchers.IO, ensuring upstream operations run on that dispatcher.Syntax
The flowOn operator is called on a Flow to change the coroutine context of upstream flow operations. It takes a CoroutineDispatcher as a parameter.
flowOn(dispatcher): Changes the context where the flow runs.
kotlin
flow {
// emit values
}.flowOn(Dispatchers.IO)Example
This example shows a flow emitting numbers on the Dispatchers.IO thread using flowOn. The collector runs on the main thread.
kotlin
import kotlinx.coroutines.* import kotlinx.coroutines.flow.* fun main() = runBlocking { val flow = flow { println("Emitting on thread: ${Thread.currentThread().name}") emit(1) delay(100) emit(2) }.flowOn(Dispatchers.IO) // Upstream runs on IO dispatcher flow.collect { println("Collected $it on thread: ${Thread.currentThread().name}") } }
Output
Emitting on thread: DefaultDispatcher-worker-1
Collected 1 on thread: main
Collected 2 on thread: main
Common Pitfalls
One common mistake is placing flowOn after terminal operators like collect, which has no effect because flowOn only affects upstream flow operations. Another pitfall is misunderstanding that flowOn changes the context only for upstream, not downstream.
kotlin
import kotlinx.coroutines.* import kotlinx.coroutines.flow.* fun main() = runBlocking { val flow = flow { println("Emitting on thread: ${Thread.currentThread().name}") emit(1) } // Wrong: flowOn after collect does nothing flow.collect { println("Collected $it on thread: ${Thread.currentThread().name}") } // .flowOn(Dispatchers.IO) This has no effect // Correct usage flow.flowOn(Dispatchers.IO).collect { println("Collected $it on thread: ${Thread.currentThread().name}") } }
Output
Emitting on thread: main
Collected 1 on thread: main
Emitting on thread: DefaultDispatcher-worker-1
Collected 1 on thread: main
Quick Reference
- flowOn(dispatcher): Changes the coroutine context for upstream flow operations.
- Use
Dispatchers.IOfor blocking IO tasks. - Use
Dispatchers.Defaultfor CPU-intensive tasks. - Place
flowOnbefore terminal operators likecollect.
Key Takeaways
Use flowOn to switch the coroutine context of upstream flow operations for better thread management.
Place flowOn before terminal operators like collect to have effect.
flowOn changes the context only for upstream, not downstream operations.
Common dispatchers are Dispatchers.IO for IO tasks and Dispatchers.Default for CPU tasks.
flowOn helps keep UI responsive by moving heavy work off the main thread.