Flow 进阶:14. 改变上下文的错误方式 (withContext)

本篇解析 example-flow-14.kt。探讨为什么不能在 Flow 内部使用 withContext

1. 核心禁忌:Flow 不允许在发射逻辑中使用 withContext

如果你在 flow { ... } 内部尝试使用 withContext 来改变发射(emit)时的线程环境,程序会直接抛出 IllegalStateException

错误示范:

1
2
3
4
5
6
7
8
fun simple(): Flow<Int> = flow {
// ❌ 错误做法:在 flow 内部改变上下文
kotlinx.coroutines.withContext(Dispatchers.Default) {
for (i in 1..3) {
emit(i) // 这里会报错!
}
}
}

2. 为什么这样设计?

Flow 必须保证上下文保存属性。这意味着 emit 必须和 collect 在同一个上下文中。如果 flow 构建器能随意切换线程发数据,那么 collect 的代码就无法预测自己会在哪个线程运行,这会导致严重的线程安全问题。

3. 开发者感悟

这是一个非常重要的设计约束。它强迫开发者使用官方推荐的方式来切换线程,从而保持流的结构清晰且线程安全。如果你需要切换发射端的线程,请使用下一节介绍的 flowOn

,