0
0
KotlinHow-ToBeginner · 3 min read

How to Collect Flow in Kotlin: Simple Guide with Examples

In Kotlin, you collect a Flow by calling the collect terminal operator inside a coroutine. This suspending function gathers emitted values from the flow and lets you handle them one by one.
📐

Syntax

The basic syntax to collect a Flow is by calling collect { value -> } inside a coroutine scope. The collect function is a suspending function, so it must be called from a coroutine or another suspending function.

  • flow: The source of asynchronous data.
  • collect: Terminal operator that triggers the flow to start emitting.
  • { value -> }: Lambda to handle each emitted value.
kotlin
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking

fun simpleFlow(): Flow<Int> = flow {
    emit(1)
    emit(2)
    emit(3)
}

fun main() = runBlocking {
    simpleFlow().collect { value ->
        println("Received $value")
    }
}
Output
Received 1 Received 2 Received 3
💻

Example

This example shows how to create a flow that emits numbers and collect them to print each value. It demonstrates the use of flow, emit, and collect inside a coroutine.

kotlin
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking

fun numberFlow() = flow {
    for (i in 1..5) {
        emit(i) // emit next number
    }
}

fun main() = runBlocking {
    numberFlow().collect { number ->
        println("Number: $number")
    }
}
Output
Number: 1 Number: 2 Number: 3 Number: 4 Number: 5
⚠️

Common Pitfalls

Common mistakes when collecting flows include:

  • Calling collect outside a coroutine or suspending function, causing a compile error.
  • Not handling cancellation properly, which can lead to leaks.
  • Using blocking code inside collect which can freeze the coroutine.

Always use collect inside runBlocking, launch, or other coroutine builders.

kotlin
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking

fun badExample() = flow {
    emit(1)
}

fun main() {
    // This will cause a compile error because collect is suspending
    // badExample().collect { println(it) }
}

// Correct way:
fun mainCorrect() = runBlocking {
    badExample().collect { println(it) }
}
📊

Quick Reference

Remember these key points when collecting flows:

  • Use a coroutine scope: collect is suspending and needs a coroutine.
  • Handle emissions: Use the lambda inside collect to process each value.
  • Flows are cold: They start emitting only when collected.

Key Takeaways

Use the suspending function collect inside a coroutine to receive flow emissions.
Flows start emitting only when collect is called, so always collect to get data.
Never call collect outside a coroutine or suspending context to avoid errors.
Handle each emitted value inside the lambda passed to collect.
Use runBlocking or launch to create coroutine scope for collecting flows.