Terminal Operators

Starting the Flow

A terminal operator is a suspend function that starts collection and waits for the result.

Example

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val prices = flowOf(499, 1299, 199, 899)

    println("toList: ${prices.toList()}")
    println("first:  ${prices.first()}")
    println("first > 1000: ${prices.first { it > 1000 }}")
    println("count:  ${prices.count()}")
    println("reduce: ${prices.reduce { a, b -> a + b }}")
    println("fold:   ${prices.fold(0) { acc, p -> acc + p / 100 }}")
    println("single: ${flowOf("only").single()}")
    println("firstOrNull on empty: ${emptyFlow<Int>().firstOrNull()}")
}

Output

toList: [499, 1299, 199, 899]
first:  499
first > 1000: 1299
count:  4
reduce: 2896
fold:   25
single: only
firstOrNull on empty: null

launchIn

Example

collect suspends until the flow ends. launchIn(scope) collects in a new coroutine and returns a Job, so you can collect several flows side by side.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val job = flow { repeat(5) { delay(100); emit(it) } }
        .onEach { println("tick $it") }
        .launchIn(this)

    delay(350)
    job.cancel()
    println("Stopped collecting")
}

Output

tick 0
tick 1
tick 2
Stopped collecting

Tip: In Android UI code, collect with repeatOnLifecycle(Lifecycle.State.STARTED) or collectAsStateWithLifecycle() in Compose, so collection stops when the app goes to the background.