Kotlin Flow 是 Kotlin 协程生态中专门处理异步、连续数据流 的 API,官方推荐的响应式编程利器。下面按照"创建 → 加工 → 收集 → 线程切换 → 生命周期管理"的顺序,一次性讲透 Flow 的核心用法与最佳实践。
1. 创建 Flow(生产者)
方式 | 场景示例 |
---|---|
flow { ... } 通用构造器 |
手动 emit 发射任意值,可调用挂起函数 |
flowOf(...) |
快速把固定元素转成 Flow |
.asFlow() |
把集合、序列、Range 直接变 Flow |
kotlin
val tickerFlow = flow {
while (true) {
emit(api.fetchNews()) // 网络请求
delay(5000) // 每 5 秒拉一次
}
}
2. 加工 Flow(中间操作符)
所有中间操作都是 冷流、惰性执行,直到被末端操作符触发。
常用链式操作:
kotlin
flow
.filter { it.isNotEmpty() } // 过滤
.map { it.toUiModel() } // 转换
.distinctUntilChanged() // 去重
.onEach { cache(it) } // 副作用
3. 收集 Flow(末端操作符)
操作符 | 作用 |
---|---|
collect |
最通用,挂起函数,需协程作用域 |
collectLatest |
新值到达时取消旧收集,适合搜索框防抖 |
toList() / first() / single() |
终端快捷函数 |
kotlin
lifecycleScope.launchWhenStarted {
vm.newsFlow.collect { list ->
adapter.submitList(list)
}
}
4. 线程切换
使用 flowOn
仅改变上游执行线程,下游仍在原作用域线程。
kotlin
flow
.map { heavyCpu(it) } // 默认线程
.flowOn(Dispatchers.Default) // 改到 Default
.collect { updateUI(it) } // 回到主线程
5. Android 生命周期级 Flow
作用域 | 说明 |
---|---|
viewModelScope |
ViewModel 销毁时自动取消 |
lifecycleScope |
Activity/Fragment 生命周期作用域 |
repeatOnLifecycle |
生命周期安全收集(官方推荐) |
kotlin
// 在 Fragment 中
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
vm.uiState.collect { render(it) }
}
}
6. StateFlow & SharedFlow(UI 状态专用)
类型 | 特点 | 典型用法 |
---|---|---|
StateFlow<T> |
有初始值、粘性、只保留最新值 | UI 单向状态 |
SharedFlow<T> |
无初始值、可配置重播、支持多订阅 | 事件总线 |
ViewModel → UI 的最简模板:
kotlin
class VM : ViewModel() {
private val _state = MutableStateFlow(Loading)
val state = _state.asStateFlow()
fun load() = viewModelScope.launch {
_state.value = repo.load()
}
}
在 Compose 中:
kotlin
val state by vm.state.collectAsStateWithLifecycle()
7. 取消与背压
- 协程作用域取消 → Flow 自动结束。
- 使用
cancellable()
操作符显式支持取消检查。 buffer()
/conflate()
/collectLatest()
处理背压。
8. 完整示例:网络 → 缓存 → UI
kotlin
class NewsRepo(
private val api: NewsApi
) {
fun news(): Flow<List<Article>> = flow {
while (true) {
emit(api.fetch()) // 网络
delay(30_000) // 30 秒轮询
}
}
.flowOn(Dispatchers.IO) // 网络线程
.onEach { cache.save(it) } // 缓存
.catch { emit(cache.get()) } // 失败兜底
}
9. 一站式学习资源
- 官方文档中文版 (含 Codelab):
developer.android.com/kotlin/flow... - 掘金系列教程 (含源码):
juejin.cn/post/733675... - Kotlin 官方文档 (深度原理):
book.kotlincn.net/text/flow.h...
一句话总结:
Flow = 协程 + 响应式,把"一次性"的 suspend 函数升级为"持续不断"的异步数据流,Android 官方推荐的现代异步方案。