Careeroza
Combining Flows
zip and combine
| Operator | Emits when | Use for |
|---|---|---|
zip | both flows have a new value (pairs them 1:1) | matching items from two sources |
combine | either flow emits (uses latest of the other) | UI state from several inputs: filters + data |
merge | any flow emits (same type) | several event sources into one |
Example
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val names = flowOf("Asha", "Ravi", "Meena")
val marks = flowOf(91, 78, 85)
names.zip(marks) { n, m -> "$n: $m" }.collect { println("zip -> $it") }
val price = flow { emit(1000); delay(200); emit(1200) }
val discount = flow { delay(100); emit(10); delay(200); emit(20) }
combine(price, discount) { p, d -> "price=$p discount=$d% pay=${p - p * d / 100}" }
.collect { println("combine -> $it") }
merge(flowOf("click"), flowOf("scroll")).toList().sorted().forEach { println("merge -> $it") }
}Output
zip -> Asha: 91 zip -> Ravi: 78 zip -> Meena: 85 combine -> price=1000 discount=10% pay=900 combine -> price=1200 discount=10% pay=1080 combine -> price=1200 discount=20% pay=960 merge -> click merge -> scroll
Flattening: flatMapConcat and flatMapLatest
Example
flatMapConcat runs inner flows one after another. flatMapLatest cancels the previous inner flow when a new value arrives: perfect for search.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun searchApi(q: String): Flow<String> = flow {
delay(150)
emit("results for '$q'")
}
@OptIn(ExperimentalCoroutinesApi::class)
fun main() = runBlocking {
flowOf(1, 2)
.flatMapConcat { id -> flowOf("order $id: item A", "order $id: item B") }
.collect { println(it) }
val queries = flow {
emit("k"); delay(100)
emit("ko"); delay(100)
emit("kotlin")
}
queries.flatMapLatest { searchApi(it) }.collect { println(it) }
}Output
order 1: item A order 1: item B order 2: item A order 2: item B results for 'kotlin'