Search⌘ K
AI Features

Characteristics, Elements, and Real-life Use Cases of Flow

Explore the characteristics and key elements of Kotlin Flow, including its terminal and intermediate operations. Learn how Flow works with coroutines to manage asynchronous data streams in practical scenarios like UI events, database changes, and network responses. Understand how to control concurrency and why Flow often replaces channels for reactive programming on Android.

The characteristics of Flow

The terminal operations of Flow (like collect) suspend a coroutine instead of blocking a thread. They also support other coroutine functionalities, such as respecting the coroutine context and handling exceptions. We can cancel flow processing, and structured concurrency is supported out of the box. The flow builder is not suspending and does not require any scope. The terminal operation suspends and builds a relation to its parent coroutine (similar to the coroutineScope function).

Example

The example below shows how the CoroutineName context is passed from collect to the lambda expression in the flow builder. It also indicates that launch cancellation also leads to proper flow processing cancellation.

package kotlinx.coroutines.app
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

// Notice, that this function is not suspending
// and does not need CoroutineScope
fun usersFlow(): Flow<String> = flow {
    repeat(3) {
        delay(1000)
        val ctx = currentCoroutineContext()
        val name = ctx[CoroutineName]?.name
        emit("User$it in $name")
    }
}

suspend fun main() {
    val users = usersFlow()

    withContext(CoroutineName("Name")) {
        val job = launch {
            // collect is suspending
            users.collect { println(it) }
        }

        launch {
            delay(2100)
            println("I got enough")
            job.cancel()
        }
    }
}
Passing CoroutineName context

Flow nomenclature

Every flow consists of a few elements:

  • The flow needs to start somewhere. It often starts with a flow builder, conversion from a different object, or helper function. We will explain an essential option in the next chapter, “
...