Kotlin Tutorial · Advanced Kotlin · Lesson 27 of 31

Kotlin Flow

Handle streams of values asynchronously with Flow: building, transforming, collecting and StateFlow.

Create a free account to save this page, take notes and track your progress. Sign in

Cold flows

A Flow emits a sequence of values over time. It's cold: nothing runs until you collect. Operators such as map, filter, take and onEach work like collection operations but are suspending.

Building and collecting a flow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking

fun prices(): Flow<Double> = flow {
    println("flow started")
    for (p in listOf(10.0, 10.5, 9.8, 11.2)) {
        delay(10)
        emit(p)
    }
}

fun main() = runBlocking {
    val flow = prices().map { it * 1.2 }.filter { it > 12 }
    println("nothing has run yet")
    flow.collect { println("price with tax: ${"%.2f".format(it)}") }
    println("max: ${prices().reduce { a, b -> maxOf(a, b) }}")
}

Output

nothing has run yet
flow started
price with tax: 12.60
price with tax: 13.44
flow started
max: 11.2

Run this on your computer — see “Get Started” for setup.

StateFlow

StateFlow is a hot flow that always holds a current value: the standard way to expose UI state from an Android ViewModel. Collectors get the latest value and every update.

StateFlow for UI state
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

class CartViewModel {
    private val _count = MutableStateFlow(0)
    val count: StateFlow<Int> = _count.asStateFlow()
    fun add() = _count.update { it + 1 }
}

fun main() = runBlocking {
    val vm = CartViewModel()
    val ui = launch {
        vm.count.take(3).collect { println("render badge: $it") }
    }
    delay(50)
    vm.add()
    delay(50)
    vm.add()
    ui.join()
    println("final: ${vm.count.value}")
}

Output

render badge: 0
render badge: 1
render badge: 2
final: 2

Run this on your computer — see “Get Started” for setup.

Test yourself

What does it mean that a Flow is cold?

  1. It caches values
  2. Its code runs only when something collects it
  3. It runs on a background thread
  4. It can't be cancelled
Show answer

Answer: Its code runs only when something collects it

Was this page helpful?