Flow 是一种用于处理异步数据流的强大工具,它基于协程实现,支持响应式编程模式。
Flow 是一个冷流(Cold Stream),即只有在被收集(collect
)时才会开始执行,类似于 Kotlin 序列(Sequence)的惰性求值特性。它可以异步地发射多个值,支持背压(Backpressure)机制。
Dispatchers.IO
、Dispatchers.Main
)中执行。suspend
函数返回单个值不同,Flow 可以返回多个值。flow
构建器:最基本的构建方式,使用 flow
关键字创建val numbersFlow = flow {
for (i in 1..3) {
delay(100) // 模拟异步操作
emit(i) // 发射值
}
}
// 收集 Flow
launch {
numbersFlow.collect { value ->
println(value) // 输出: 1, 2, 3
}
}
flowOf
静态工厂:创建包含固定值的 Flowval fruitsFlow = flowOf("Apple", "Banana", "Cherry")
asFlow
扩展函数:将其他类型(如 List、Sequence)转换为 Flowval listFlow = listOf(1, 2, 3).asFlow()
numbersFlow.map { it * 2 }.collect { println(it) } // 输出: 2, 4, 6
numbersFlow.filter { it % 2 == 0 }.collect() // 只输出偶数
take
:只取前 n 个元素:
numbersFlow.take(2).collect() // 只输出 1, 2
zip
:合并两个 Flow 的元素
val lettersFlow = flowOf("A", "B", "C")
numbersFlow.zip(lettersFlow) { num, letter -> "$num-$letter" }
.collect() // 输出: "1-A", "2-B", "3-C"
combine
:合并最新值:
numbersFlow.combine(lettersFlow) { num, letter -> "$num-$letter" }
.collect() // 输出: "3-A", "3-B", "3-C"
catch
:捕获 Flow 中的异常
retry
:重试失败的 Flow
numbersFlow.retry(3) // 失败时重试3次
onStart
/onCompletion
:在 Flow 开始 / 结束时执行操作:
numbersFlow
.onStart { println("Flow started") }
.onCompletion { println("Flow completed") }
.collect()
cancellable
:使 Flow 可被取消:
numbersFlow.cancellable().collect()
特性 | 冷流(Cold Flow) | 热流(Hot Flow) |
---|---|---|
数据发射时机 | 仅在被 collect 时启动数据发射 |
无论是否有收集者,数据发射独立进行 |
收集者影响 | 每个收集者触发独立的数据流(重新执行构建逻辑) | 所有收集者共享同一数据流(数据发射与收集者无关) |
状态共享 | 不共享状态,每个收集者拥有独立上下文 | 共享状态或发射历史,收集者可获取已发射的数据 |
典型实现 | flow 、flowOf 、asFlow 等构建的流 |
StateFlow 、SharedFlow 、callbackFlow |
代码示例:
// 冷流示例:每次 collect 都会重新执行 flow 构建逻辑
val coldFlow = flow {
println("冷流开始发射数据")
for (i in 1..3) {
delay(500)
emit(i)
}
}
// 热流示例:StateFlow 始终维护最新值,收集者直接获取当前状态
val hotFlow = MutableStateFlow(0)
// 先更新热流数据,再收集
hotFlow.value = 100
launch {
hotFlow.collect { println("热流收集值:$it") } // 输出:100
}
// 冷流需要先收集,才会开始发射
launch {
println("开始收集冷流")
coldFlow.collect { println("冷流收集值:$it") }
}
2.冷流的底层实现原理
冷流的核心特性是惰性求值,其底层实现基于以下机制:
flow
构建器的本质:
flow
构建器返回一个 FlowImpl
实例,该实例在 collect
时才会执行 flow
闭包内的代码。闭包中的 emit
操作通过 FlowCollector
接口实现数据发射。
协程上下文绑定:
冷流的执行上下文由 collect
所在的协程作用域决定,每次 collect
都会创建独立的协程执行路径。
冷流的背压处理:
冷流通过操作符实现背压,核心原理是在收集端控制数据接收节奏:
buffer()
操作符:
创建内部缓冲区(基于 Channel
),当发射速度超过收集速度时,未被收集的数据暂存至缓冲区。
conflate()
操作符:
丢弃中间未被收集的数据,仅保留最新值,适用于实时数据场景(如传感器数据)。
底层实现代码片段:
// flow 构建器的简化实现(Kotlin 标准库)
public fun flow(block: suspend FlowCollector.() -> Unit): Flow =
SafeFlow(block) // SafeFlow 是 Flow 的实现类,封装了收集逻辑
// buffer 操作符的核心逻辑
public fun Flow.buffer(
capacity: Int = BUFFERED_COLLECTION_DEFAULT_CAPACITY
): Flow = ChannelFlow(capacity) { collector ->
val channel = Channel(capacity)
// 发射端将数据存入 Channel
collect { value -> channel.send(value) }
// 收集端从 Channel 取出数据
channel.consumeEach { collector.emit(it) }
}
callbackFlow
是一个 Flow 构建器,用于将回调式 API 转换为 Flow:
Player.Listener
、Java 的 Future
等)。Channel
实现背压处理,支持各种背压策略(如 BUFFERED
、CONFLATED
)。关键接口
trySend(value)
:向 Flow 发送值,非阻塞操作,可能因缓冲区满而失败。send(value)
:挂起函数,阻塞直到值被接收或通道关闭。awaitClose()
:注册清理逻辑,在 Flow 收集取消时调用。用于资源清理3.热流的底层实现原理
StateFlow 是热流的典型实现,核心特性是维护最新状态,其底层原理如下:
MutableStateFlow
继承自 AbstractStateFlow
,内部通过 AtomicReference
存储最新值,并使用 SafeMutableStateFlow
封装线程安全操作。collect
操作会创建一个 StateFlowCollector
,通过 Job
管理协程生命周期,确保状态更新时通知所有活跃收集者。conflate
背压策略)。SharedFlow 支持多收集者共享数据流,底层实现更复杂:
Channel
实现数据缓冲,可配置缓冲区大小(UNLIMITED
、BUFFERED
等)。MutableSharedFlowImpl
维护收集者列表,通过 BroadcastChannel
实现数据广播。replay
参数配置历史数据保留策略)。// StateFlow 简化实现
public class MutableStateFlow(initialValue: T) : AbstractStateFlow(initialValue),
MutableStateFlow {
private val state = AtomicReference(initialValue)
override val value: T
get() = state.value
override fun setValue(value: T) {
state.set(value)
// 通知所有收集者更新状态
super.emitValue(value)
}
// 收集者注册逻辑
override fun collectSafely(collector: FlowCollector, job: Job) {
val currentValue = state.value
// 先发送当前值(热流特性)
collector.emit(currentValue)
// 注册状态变更监听
// ...(省略具体实现)
}
}
// SharedFlow 核心构造逻辑
public fun MutableSharedFlow(
replay: Int = 0,
extraBufferCapacity: Int = 0,
onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND
): MutableSharedFlow = when {
replay > 0 || extraBufferCapacity > 0 -> {
// 带缓冲区和历史数据的实现
MutableSharedFlowImpl(replay, extraBufferCapacity, onBufferOverflow)
}
else -> {
// 无缓冲的简化实现
NoBufferSharedFlow(onBufferOverflow)
}
}
冷热流转换:
通过 stateIn
或 shareIn
操作符实现:
val coldFlow = flow { ... }
// 冷流转热流(StateFlow)
val stateFlow = coldFlow.stateIn(
scope = CoroutineScope(Dispatchers.Main),
started = SharingStarted.WhileSubscribed(5000), // 5秒无收集者则停止
initialValue = 0
)
// 冷流转热流(SharedFlow)
val sharedFlow = coldFlow.shareIn(
scope = CoroutineScope(Dispatchers.IO),
replay = 1, // 保留最后1个值
started = SharingStarted.Eagerly
)
冷流适用场景:一次性数据加载(如网络请求结果流),按需生成数据(如用户触发事件后的数据流)。
热流适用场景:共享状态管理(如 ViewModel 中的状态流),多组件订阅的实时数据(如传感器数据、网络连接状态)。
当 Flow 发射数据的速度快于收集速度时,使用背压策略处理:
buffer:缓冲数据
numbersFlow.buffer(10) // 缓存10个元素
conflate
:只处理最新值:
numbersFlow.conflate()
collectLatest
:取消并重新启动收集器:
numbersFlow.collectLatest { value ->
delay(1000)
println(value)
}