4.1 冷流与热流本质解析
4.1.1 冷流(Cold Flow)特性与实现
核心特性:
- 每次收集(collect)时启动新的执行
- 数据源独立于收集者存在
- 无共享状态,适合数据转换操作
scss
// 冷流创建示例
fun fetchUserData(): Flow<UserData> = flow {
// 每次collect都会执行
val profile = api.getProfile() // 挂起函数
emit(profile)
val friends = api.getFriends() // 挂起函数
emit(friends)
val posts = api.getPosts() // 挂起函数
emit(posts)
}
// 使用:两次收集触发两次完整执行
viewModelScope.launch { fetchUserData().collect() } // 执行1
viewModelScope.launch { fetchUserData().collect() } // 执行2
冷流实现原理 :
4.1.2 热流(Hot Flow)特性与实现
核心特性:
- 数据流独立于收集者存在
- 多个收集者共享同一数据源
- 新收集者可能错过历史数据
kotlin
// SharedFlow创建(热流)
private val _events = MutableSharedFlow<Event>(
replay = 3, // 新订阅者重放3个事件
extraBufferCapacity = 10 // 额外缓冲区
)
val events: SharedFlow<Event> = _events.asSharedFlow()
// 发送事件
fun sendEvent(event: Event) {
viewModelScope.launch {
_events.emit(event)
}
}
// 多个收集者
collector1.collect { /* 收到事件 */ }
collector2.collect { /* 收到相同事件 */ }
热流实现原理:

4.1.3 冷热流转换机制
冷流转热流:
ini
// 将数据库查询冷流转为热流
val userFlow: Flow<List<User>> = userDao.getUsers()
val hotUserFlow = userFlow.shareIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000), // 5秒无订阅者停止
replay = 1 // 新订阅者获取最新值
)
// 多个UI组件共享同一查询结果
headerView.collectLatest { hotUserFlow.collect() }
listView.collectLatest { hotUserFlow.collect() }
热流转冷流:
kotlin
// SharedFlow转为冷流(不推荐,语义不符)
fun SharedFlow<T>.asColdFlow(): Flow<T> = flow {
collect { value ->
emit(value)
}
}
4.2 背压(Backpressure)处理策略
4.2.1 背压问题场景分析

4.2.2 背压解决方案对比
策略 | 机制 | 适用场景 | 实现方式 |
---|---|---|---|
BUFFER | 缓冲未处理数据 | 消费偶发延迟 | .buffer() |
DROP | 丢弃无法处理的数据 | 允许数据丢失 | .buffer(onBufferOverflow=DROP) |
LATEST | 保留最新值 | 状态更新场景 | .conflate() |
SUSPEND | 挂起生产者 | 必须保证数据完整 | 默认行为 |
4.2.3 背压控制源码解析
kotlin
// ChannelFlow.kt#L120
internal open class ChannelFlowBuilder<T>(
private val block: suspend ProducerScope<T>.() -> Unit,
context: CoroutineContext,
capacity: Int,
onBufferOverflow: BufferOverflow
) : ChannelFlow<T>(context, capacity, onBufferOverflow) {
// 核心:创建通道处理背压
override suspend fun collectTo(scope: ProducerScope<T>) {
block(scope)
}
}
// 缓冲操作符实现
public fun <T> Flow<T>.buffer(
capacity: Int = BUFFERED,
onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND
): Flow<T> {
// 创建带缓冲的ChannelFlow
return ChannelFlowOperator(this, capacity, onBufferOverflow)
}
背压处理流程:
- 收集操作触发流执行
- 数据发射到ChannelFlow的缓冲区
- 根据缓冲策略处理溢出
- 消费者从缓冲区按能力取数据
4.3 Flow操作符原理剖析
4.3.1 操作符分类体系

4.3.2 核心操作符实现
Map操作符:
kotlin
// Flow.map扩展实现
public inline fun <T, R> Flow<T>.map(crossinline transform: suspend (T) -> R): Flow<R> = transform { value ->
// 对每个值应用转换
return@transform emit(transform(value))
}
// 底层transform实现
public inline fun <T, R> Flow<T>.transform(
crossinline transform: suspend FlowCollector<R>.(value: T) -> Unit
): Flow<R> = flow {
// 安全收集原始流
collect { value ->
// 调用转换函数
transform(value)
}
}
DistinctUntilChanged操作符:
kotlin
// 有状态操作符实现
public fun <T> Flow<T>.distinctUntilChanged(): Flow<T> = distinctUntilChangedBy { it }
public fun <T, K> Flow<T>.distinctUntilChangedBy(
selector: (T) -> K
): Flow<T> = flow {
// 保存前一个值
var previousKey: Any? = UNDEFINED
collect { value ->
val key = selector(value)
// 检查键值是否变化
if (previousKey === UNDEFINED || previousKey != key) {
previousKey = key
emit(value)
}
}
}
4.3.3 自定义高性能操作符
scss
// 批处理操作符优化
fun <T> Flow<T>.batch(size: Int): Flow<List<T>> = flow {
val batch = ArrayList<T>(size)
collect { value ->
batch.add(value)
if (batch.size == size) {
emit(batch.toList())
batch.clear()
}
}
// 处理剩余元素
if (batch.isNotEmpty()) {
emit(batch.toList())
}
}
// 使用示例
dataSourceFlow
.batch(50) // 每50条批处理一次
.map { processBatch(it) }
.collect { ... }
4.4 StateFlow与SharedFlow揭秘
4.4.1 StateFlow设计哲学
核心特性:
- 必须有初始值
- 仅保留最新值
- 值相等时不更新
- 强一致性:收集者总是看到最新值
kotlin
// StateFlow实现原理(简化)
public class MutableStateFlow<T>(
private var _state: T
) : StateFlow<T> {
// 原子更新状态
override fun compareAndSet(expect: T, update: T): Boolean {
return _state.compareAndSet(expect, update)
}
// 收集者实现
override suspend fun collect(collector: FlowCollector<T>) {
val slot = allocateSlot()
try {
while (true) {
// 检查值变化
if (slot.takePending()) {
collector.emit(slot.value)
}
// 挂起等待更新
slot.awaitPending()
}
} finally {
freeSlot(slot)
}
}
}
4.4.2 SharedFlow核心架构
关键参数:
replay
:重播给新订阅者的数据量extraBufferCapacity
:额外缓冲区大小onBufferOverflow
:溢出策略(SUSPEND/DROP_OLDEST/DROP_LATEST)
4.4.3 StateFlow与SharedFlow对比
特性 | StateFlow | SharedFlow |
---|---|---|
初始值 | 必须有 | 可选 |
数据重播 | 总是最新值 | 可配置重播数量 |
值去重 | 自动(equals) | 不自动去重 |
订阅者状态同步 | 立即获取当前值 | 获取重播缓存 |
适用场景 | 状态管理 | 事件广播 |
4.5 Flow与LiveData互操作
4.5.1 LiveData转Flow
kotlin
// 扩展函数实现
fun <T> LiveData<T>.asFlow(): Flow<T> = flow {
val observer = object : Observer<T> {
override fun onChanged(value: T) {
try {
emit(value)
} catch (e: Exception) {
// 处理异常
}
}
}
// 注册观察者
withContext(Dispatchers.Main.immediate) {
observeForever(observer)
}
try {
// 等待流取消
awaitCancellation()
} finally {
// 移除观察者
withContext(Dispatchers.Main.immediate) {
removeObserver(observer)
}
}
}
// 使用示例
lifecycleScope.launch {
liveData.asFlow()
.filter { it != null }
.collect { ... }
}
4.5.2 Flow转LiveData
kotlin
// 使用androidx.lifecycle扩展
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.0"
// 转换示例
val userLiveData: LiveData<User> = userFlow
.filter { it.isActive }
.asLiveData(viewModelScope.coroutineContext)
4.6 Flow调试与性能优化
4.6.1 调试工具使用
kotlin
// 启用调试模式
fun debugFlow<T>(flow: Flow<T>): Flow<T> = flow
.onStart { log("Flow started") }
.onEach { log("Emitting value: $it") }
.onCompletion { log("Flow completed") }
.catch { log("Flow error", it) }
// 使用
userFlow
.debugFlow()
.collect { ... }
4.6.2 性能优化技巧
- 避免频繁更新:
scss
// 防抖处理
searchFlow
.debounce(300)
.distinctUntilChanged()
.collect { ... }
- 批处理优化:
scss
// 合并UI更新
flow
.batch(10) // 自定义批处理操作符
.onEach { updateUI(it) } // 每10个更新一次UI
.collect()
- 线程调度优化:
scss
// 减少主线程切换
dataFlow
.flowOn(Dispatchers.Default) // 上游在IO线程
.map { ... } // 仍在IO线程
.onEach { ... } // 仍在IO线程
.flowOn(Dispatchers.Main) // 下游切换到主线程
.collect()
4.7 复杂流处理模式
4.7.1 多流合并
scss
// 组合多个数据源
fun combineUserData(): Flow<UserViewState> {
return combine(
userProfileFlow,
userFriendsFlow,
userPostsFlow
) { profile, friends, posts ->
UserViewState(profile, friends, posts)
}
.catch { emit(ErrorState(it)) }
}
// 使用
combineUserData()
.onEach { renderUI(it) }
.launchIn(viewModelScope)
4.7.2 错误处理策略
csharp
// 分层错误处理
dataFlow
.onEach { /* 业务操作 */ }
.catch { cause ->
// 1. 本地恢复尝试
if (cause is NetworkException) {
emit(fallbackData)
} else {
// 2. 重新抛出
throw cause
}
}
.retryWhen { cause, attempt ->
// 3. 重试策略
if (cause is IOException && attempt < 3) {
delay(attempt * 1000L)
true
} else {
false
}
}
.collect()
本章小结
本章深入解析了Flow响应式编程的核心内容:
- 冷热流本质:冷流按需生产,热流独立存在
- 背压处理:四大策略应对数据积压
- 操作符原理:无状态与有状态操作符实现
- StateFlow/SharedFlow:状态管理与事件广播方案
- LiveData互操作:双向转换实现
- 性能优化:调试工具与优化技巧
- 复杂流处理:多流合并与分层错误处理
在下一章,我们将探讨协程与Android系统的深度整合,包括Jetpack组件集成、UI编程最佳实践以及资源安全访问策略。