Skip to content

Flow 契约与安全

异常透明性 (Exception Transparency)

Flow 必须对下游异常透明。 这意味着,collect { ... } 中的代码抛出的异常,不能被 flow { ... } 内部的 try-catch 捕获。

kotlin
// ❌ 违规代码
flow {
    try {
        emit(1)
    } catch (e: Exception) {
        // 这会捕获下游 collect 中的异常!
        // 导致下游无法正常传播错误,也无法响应取消。
        println("Caught downstream error: $e")
    }
}

正确做法:只捕获上游逻辑的异常。

kotlin
flow {
    try {
        val data = loadData() // 若这里出错,catch 会捕获
        emit(data)
    } catch (e: Exception) {
        emit(fallbackData) // ✅ 仅处理上游错误
    }
}

并发发射:channelFlow

flow { ... } 是串行的。如果你需要在流内部启动多个协程同时发射数据,必须使用 channelFlow

kotlin
fun mergedData(): Flow<Data> = channelFlow {
    // 两个子协程并发运行
    launch { send(apiA.fetch()) } 
    launch { send(apiB.fetch()) }
}

上下文检查 (Context Preservation)

Flow 库在运行时会通过 SafeCollector 检查上下文。 如果 emit 发生的线程与 collect 时的线程不一致(且没有使用 flowOn 声明),会直接抛出 IllegalStateException