...

/

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

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

Learn about the characteristics and elements of flow using real-life examples.

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