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() } } }
Flow
nomenclature
Every flow consists of a few elements:
- The flow needs to start somewhere. It often starts with a
flow