# Dispatchers and Flow — Kotlin

Source: https://www.skillbyai.com/en/kotlin/co-flow

> Choosing threads and streaming values.

## Where coroutines run and how values stream

A **dispatcher** decides which threads run a coroutine: `Dispatchers.Default` for CPU-bound work, `Dispatchers.IO` for blocking I/O such as JDBC or file access, and `Dispatchers.Main` for UI threads on Android and desktop. Switch with `withContext(Dispatchers.IO) { ... }`; well-written suspend functions are **main-safe** by doing this internally. A `Flow<T>` is a **cold** asynchronous stream: the `flow { emit(x) }` builder runs each time it is collected. Operators like `map`, `filter`, `debounce` and `catch` transform it, `flowOn` changes the upstream dispatcher, and `collect` is the terminal operator. `StateFlow` and `SharedFlow` are **hot** flows for state and events shared among collectors.

## A polling flow and a state holder

Cold Flow and hot StateFlow.

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

fun prices(symbol: String): Flow<Double> = flow {
    while (true) {
        emit(fetchPrice(symbol))      // runs per collector
        delay(1_000)
    }
}.flowOn(Dispatchers.IO)              // upstream runs on IO

suspend fun fetchPrice(symbol: String): Double = 100.0   // placeholder for a real call

class CounterModel {
    private val _count = MutableStateFlow(0)
    val count: StateFlow<Int> = _count.asStateFlow()     // read-only view
    fun increment() { _count.update { it + 1 } }
}

suspend fun watch() {
    prices("KT")
        .map { it * 1.1 }
        .take(3)
        .catch { e -> println("error: ${e.message}") }
        .collect { println(it) }
}
```

## Expose read-only state

Keep `MutableStateFlow` private and expose `StateFlow` via `asStateFlow()`, so only the owner can change state and everyone else observes it.

**Quiz:** Which dispatcher suits blocking file or JDBC calls?

- [x] `Dispatchers.IO`
- [ ] `Dispatchers.Main`
- [ ] `Dispatchers.Unconfined`
- [ ] No dispatcher; call them directly on the main thread

*Answer:* `Dispatchers.IO`. IO is sized for blocking operations; Default is for CPU work.
