ChannelFlow构建器详解
ChannelFlow vs Flow 核心差异
| 特性 | Flow | ChannelFlow |
|---|
| 执行模式 | 同步顺序 | 异步并发 |
| 数据传输 | 直接调用 | Channel缓冲 + emitAll |
| 背压处理 | 自然阻塞 | 可配置策略 |
| 协程支持 | 无内置作用域 | ProducerScope |
| 适用场景 | 简单数据流 | 复杂并发场景 |
执行时序对比
Flow - 同步执行
flow {
emit(1)
emit(2)
}.collect { value ->
println("收集: $value")
}
ChannelFlow - 并发执行
channelFlow {
launch { send(1) }
launch { send(2) }
}.collect { value ->
println("收集: $value")
}
缓冲区配置策略
1. 无缓冲(默认)- RENDEZVOUS
channelFlow {
send(1)
send(2)
}
特点: 严格背压,生产者必须等待消费者
2. 有限缓冲
channelFlow(capacity = 10) {
repeat(10) { send(it) }
send(10)
}
特点: 缓冲区满时阻塞
3. 无限缓冲
channelFlow(capacity = Channel.UNLIMITED) {
repeat(1000) { send(it) }
}
特点: 永不阻塞,但可能内存溢出
4. 溢出策略配置
channelFlow(
capacity = 10,
onBufferOverflow = BufferOverflow.DROP_OLDEST
) {
repeat(100) { send(it) }
}
// 三种溢出策略:
send vs trySend 详解
send - 挂起函数(可能阻塞)
channelFlow {
send(1)
send(2)
}
何时阻塞:
缓冲区满且溢出策略为 SUSPEND
无缓冲模式下没有消费者等待
trySend - 非阻塞函数
channelFlow {
val result1 = trySend(1)
val result2 = trySend(2)
if (result1.isSuccess) {
println("发送成功")
} else {
println("发送失败: ${result1.exceptionOrNull()}")
}
}
返回结果:
ChannelResult.success(Unit) - 发送成功
ChannelResult.failure(exception) - 发送失败
实际应用场景对比
1. API并发请求
fun fetchUsersFlow(ids: List<String>) = flow {
ids.forEach { id ->
emit(apiService.getUser(id))
}
}
fun fetchUsersChannelFlow(ids: List<String>) = channelFlow {
ids.forEach { id ->
launch {
send(apiService.getUser(id))
}
}
}
2. 高频数据处理
fun sensorFlow() = channelFlow<SensorData>(
capacity = 100,
onBufferOverflow = BufferOverflow.DROP_OLDEST
) {
sensorManager.registerListener(object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
trySend(SensorData(event.values, event.timestamp))
}
}, sensor, SensorManager.SENSOR_DELAY_FASTEST)
}
3. 网络回调处理
fun webSocketFlow() = channelFlow<String> {
val webSocket = client.newWebSocket(request, object : WebSocketListener() {
override fun onMessage(webSocket: WebSocket, text: String) {
trySend(text)
}
})
awaitClose { webSocket.close(1000, "Flow closed") }
}
阻塞与非阻塞场景分析
阻塞场景(使用send)
channelFlow {
send(1)
repeat(100) { send(it) }
send(data)
}
非阻塞场景(使用trySend)
channelFlow {
trySend(1)
val result = trySend(2)
trySend(3)
}
总结
- 简单顺序流 → 使用
flow - 并发复杂流 → 使用
channelFlow - 关键数据 → 使用
send(可阻塞) - 高频数据 → 使用
trySend(非阻塞) - 合理配置缓冲区 → 根据数据特性选择
capacity和溢出策略
阻塞规律: send + 缓冲区满 + SUSPEND策略 = 阻塞trySend + 任何情况 = 不阻塞- 无缓冲模式下,
send总是阻塞直到有消费者