CodeBlanks Logo Icon CodeBlanks

flowOn

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 context

The 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

Main.kt
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

Main.kt
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

Question
numbers().____(Dispatchers.IO).collect { println(it) }
Answer
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

All lessons in Intermediate