Intermediate 10 min readKotlin 2.0

Kotlin Flow — Reactive Streams Made Simple

Flow is Kotlin's way to handle streams of asynchronous data. Unlike sequences, Flow is built on coroutines and is fully asynchronous.

What You Will Learn

  • What Flow is and why use it
  • Create flows with flow { } builder
  • Collect values with collect()
  • Transform flows with map and filter
  • Understand cold vs hot flows

What is Flow?

A Flow is a cold asynchronous stream. It emits multiple values sequentially over time. Unlike a coroutine that returns one value, Flow returns many values asynchronously.
Flow requires the kotlinx-coroutines-core library.
Dependency required: implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")

Creating and Collecting a Flow

Use the flow { } builder to create a Flow. Use collect { } to receive its values.

Basic Flow

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

fun simpleFlow(): Flow<Int> = flow {
    for (i in 1..5) {
        delay(100)  // simulate async work
        emit(i)     // send value downstream
    }
}

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

flow { } is the builder. emit() sends a value to collectors. collect { } receives each emitted value. delay() is non-blocking — it suspends without blocking the thread.

Beginner Tip: Flow is "cold" — it does not run until collect() is called. Each collector starts a fresh execution of the flow.

Flow Operators

Transform and filter flows using operators — they work like collection operators but asynchronously.

map and filter

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

fun main() = runBlocking {
    val flow = flowOf(1, 2, 3, 4, 5, 6)

    flow
        .filter { it % 2 == 0 }   // keep even
        .map { it * it }           // square them
        .collect { println(it) }
}
Output
4 16 36

filter keeps only even numbers (2, 4, 6). map squares each: 4, 16, 36. Each operator returns a new Flow — no data is processed until collect is called.

flowOf and asFlow

Quick ways to create flows from existing values.

flowOf and asFlow

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

fun main() = runBlocking {
    flowOf("Kotlin", "Java", "Python")
        .map { it.uppercase() }
        .collect { println(it) }

    println("---")

    listOf(10, 20, 30).asFlow()
        .collect { println(it) }
}
Output
KOTLIN JAVA PYTHON --- 10 20 30

flowOf() creates a Flow from given values. .asFlow() converts any Iterable (List, Set, etc.) to a Flow.

Practice Exercise

Exercisemultiple choice

When does a cold Flow start emitting values?

Quick Quiz

Quick Quiz

What function sends a value downstream in a flow builder?

Frequently Asked Questions

Related Tutorials

Last updated: 2026-05-01Kotlin 2.0

Written by KotlinGuide Editorial Team · Reviewed by KotlinGuide Technical Review