flowOn

fun <T> Flow<T>.flowOn(context: CoroutineContext): Flow<T>(source)

Changes the context where this flow is executed to the given context. This operator is composable and affects only preceding operators that do not have its own context. This operator is context preserving: context does not leak into the downstream flow.

For example:

withContext(Dispatchers.Main) {
val singleValue = intFlow // will be executed on IO if context wasn't specified before
.map { ... } // Will be executed in IO
.flowOn(Dispatchers.IO)
.filter { ... } // Will be executed in Default
.flowOn(Dispatchers.Default)
.single() // Will be executed in the Main
}

For more explanation of context preservation please refer to Flow documentation.

This operator retains a sequential nature of flow if changing the context does not call for changing the dispatcher. Otherwise, if changing dispatcher is required, it collects flow emissions in one coroutine that is run using a specified context and emits them from another coroutines with the original collector's context using a channel with a default buffer size between two coroutines similarly to buffer operator, unless buffer operator is explicitly called before or after flowOn, which requests buffering behavior and specifies channel size.

Note, that flows operating across different dispatchers might lose some in-flight elements when cancelled. In particular, this operator ensures that downstream flow does not resume on cancellation even if the element was already emitted by the upstream flow.

Operator fusion

Adjacent applications of channelFlow, flowOn, buffer, and produceIn are always fused so that only one properly configured channel is used for execution.

Multiple flowOn operators fuse to a single flowOn with a combined context. The elements of the context of the first flowOn operator naturally take precedence over the elements of the second flowOn operator when they have the same context keys, for example:

flow.map { ... } // Will be executed in IO
.flowOn(Dispatchers.IO) // This one takes precedence
.flowOn(Dispatchers.Default)

Note that an instance of SharedFlow does not have an execution context by itself, so applying flowOn to a SharedFlow has not effect. See the SharedFlow documentation on Operator Fusion.

Throws

if provided context contains Job instance.