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