在现代Android开发中,响应式编程已成为处理异步数据流的标准范式。Kotlin Flow作为Coroutines家族的一员,提供了一个功能强大且符合Kotlin习惯的响应式编程解决方案。它完美解决了LiveData和RxJava的诸多痛点,让异步数据流处理变得更加直观和安全。
响应式编程演变历程

一、为什么需要Flow?传统方案的痛点
1.1 LiveData的局限性
// LiveData的典型问题
class UserRepository {
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> = _users
// 问题1:难以组合多个数据源
fun loadCombinedData() {
// 需要手动合并多个LiveData
val source1 = api.getUsers()
val source2 = localDb.getUsers()
// 合并逻辑复杂...
}
// 问题2:缺乏丰富的操作符
fun searchUsers(query: String) {
// LiveData没有debounce、filter等操作符
// 需要额外实现
}
}
1.2 RxJava的复杂性
// RxJava虽然强大但复杂
Observable.create<List<User>> { emitter ->
api.getUsers().enqueue(object : Callback<List<User>> {
override fun onResponse(call: Call<List<User>>,
response: Response<List<User>>) {
emitter.onNext(response.body()!!)
}
override fun onFailure(call: Call<List<User>>, t: Throwable) {
emitter.onError(t)
}
})
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.debounce(300, TimeUnit.MILLISECONDS) // 操作符链
.filter { users -> users.isNotEmpty() }
.subscribe({ users ->
// 处理数据
}, { error ->
// 处理错误
})
二、Flow核心概念:冷流与热流
2.1 Flow vs StateFlow/SharedFlow**

2.2 基础Flow创建
// 创建Flow的多种方式
class FlowBasics {
// 1. flow构建器(最常用)
fun createBasicFlow(): Flow<Int> = flow {
for (i in 1..10) {
delay(100) // 可挂起
emit(i) // 发射值
}
}
// 2. 集合转Flow
fun collectionToFlow(): Flow<String> {
val list = listOf("A", "B", "C")
return list.asFlow()
}
// 3. 回调转Flow
fun callbackToFlow(): Flow<Location> = callbackFlow {
val callback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
result.locations.forEach { location ->
trySend(location) // 发送到Flow
}
}
}
locationClient.requestLocationUpdates(
request, callback, Looper.getMainLooper()
)
// 当Flow收集完成时取消注册
awaitClose {
locationClient.removeLocationUpdates(callback)
}
}
// 4. StateFlow(必须有初始值)
private val _uiState = MutableStateFlow(UiState.Loading)
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
// 5. SharedFlow(可配置重播)
private val _events = MutableSharedFlow<Event>(
replay = 1, // 新订阅者收到最后1个事件
extraBufferCapacity = 10 // 额外缓冲区
)
val events: SharedFlow<Event> = _events.asSharedFlow()
}
三、Flow操作符大全:构建数据流水线
3.1 转换操作符
class TransformationOperators {
// map - 转换每个值
fun mapExample(): Flow<String> = flowOf(1, 2, 3)
.map { value -> "Number: $value" }
// transform - 更灵活的转换
fun transformExample(): Flow<String> = flowOf(1, 2, 3)
.transform { value ->
if (value % 2 == 0) {
emit("Even: $value")
} else {
emit("Odd: $value")
}
}
// mapLatest - 只处理最新的值
fun searchFlow(query: Flow<String>): Flow<List<Result>> = query
.debounce(300) // 防抖
.mapLatest { searchTerm ->
if (searchTerm.isBlank()) emptyList()
else api.search(searchTerm) // 取消之前的搜索
}
.catch { emit(emptyList()) } // 异常处理
}
3.2 过滤操作符
class FilteringOperators {
// filter - 条件过滤
fun filterExample(): Flow<Int> = flowOf(1, 2, 3, 4, 5)
.filter { it % 2 == 0 } // 只保留偶数
// take - 取前N个
fun takeExample(): Flow<Int> = flowOf(1, 2, 3, 4, 5)
.take(3) // 只取前3个:1, 2, 3
// drop - 跳过前N个
fun dropExample(): Flow<Int> = flowOf(1, 2, 3, 4, 5)
.drop(2) // 跳过前2个:3, 4, 5
// distinctUntilChanged - 去重
fun distinctExample(): Flow<String> = flowOf("A", "A", "B", "B", "A")
.distinctUntilChanged() // A, B, A
// debounce - 防抖(搜索场景)
fun searchWithDebounce(): Flow<List<Result>> {
return userInputFlow
.debounce(300) // 300ms内只取最后一个输入
.flatMapLatest { query ->
flow { emit(api.search(query)) }
}
}
}
3.3 组合操作符
class CombinationOperators {
// zip - 一对一组合
fun zipExample() {
val numbers = flowOf(1, 2, 3).onEach { delay(100) }
val letters = flowOf("A", "B", "C").onEach { delay(150) }
numbers.zip(letters) { number, letter ->
"$number$letter"
}.collect { result ->
println(result) // 1A, 2B, 3C
}
}
// combine - 最新值组合(实时)
fun combineExample() {
val userId = MutableStateFlow("user1")
val filter = MutableStateFlow(Filter.ALL)
val userData = userId.combine(filter) { id, f ->
loadUserData(id, f) // 任一更新都会触发
}
}
// flatMap系列 - 展平Flow
fun flatMapExamples() {
// flatMapConcat - 顺序执行
fun getComments(postId: String): Flow<Comment> = flow {
emit(api.getComments(postId))
}
postIdFlow.flatMapConcat { postId ->
getComments(postId) // 按顺序执行
}
// flatMapMerge - 并发执行
postIdFlow.flatMapMerge(concurrency = 3) { postId ->
getComments(postId) // 最多3个并发
}
// flatMapLatest - 只取最新
searchQueryFlow.flatMapLatest { query ->
searchApi.search(query) // 取消之前的搜索
}
}
}
3.4 异常处理操作符
class ExceptionHandling {
// catch - 捕获上游异常
fun catchExample(): Flow<Int> = flow {
emit(1)
throw RuntimeException("Error!")
}.catch { cause ->
println("Caught: $cause")
emit(-1) // 发生异常时发射默认值
}
// retry - 重试机制
fun retryExample(): Flow<Data> = flow {
emit(fetchData()) // 可能失败的操作
}.retry(retries = 3) { cause ->
// 条件重试
cause is IOException && attempt < 3
}
// 完整的异常处理链
fun completeErrorHandling(): Flow<Result<Data>> = flow {
emit(Result.loading())
val data = api.fetchData()
emit(Result.success(data))
}.catch { cause ->
emit(Result.error(cause))
}.retryWhen { cause, attempt ->
delay(attempt * 1000L) // 指数退避
attempt < 3
}
}
四、Flow在Android MVVM架构中的实战
4.1 ViewModel中的StateFlow模式**
// 使用Sealed Class表示UI状态
sealed class UiState {
object Loading : UiState()
data class Success(val data: List<User>) : UiState()
data class Error(val message: String) : UiState()
}
class UserViewModel : ViewModel() {
// 使用MutableStateFlow管理状态
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
// 使用SharedFlow处理一次性事件
private val _events = MutableSharedFlow<Event>()
val events: SharedFlow<Event> = _events.asSharedFlow()
// 加载数据
fun loadUsers() = viewModelScope.launch {
_uiState.value = UiState.Loading
userRepository.getUsers()
.onEach { users ->
_uiState.value = UiState.Success(users)
}
.catch { error ->
_uiState.value = UiState.Error(error.message ?: "Unknown error")
// 发送事件
_events.emit(Event.ShowToast("加载失败"))
}
.collect() // 开始收集
}
// 搜索功能
fun setupSearch(queryFlow: Flow<String>) = viewModelScope.launch {
queryFlow
.debounce(300)
.filter { it.length >= 2 }
.distinctUntilChanged()
.flatMapLatest { query ->
userRepository.searchUsers(query)
.catch { emit(emptyList()) }
}
.collect { results ->
_uiState.value = UiState.Success(results)
}
}
}
4.2 在Activity/Fragment中收集Flow
class UserActivity : AppCompatActivity() {
private val viewModel: UserViewModel by viewModels()
private var collectJob: Job? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 方式1:lifecycleScope自动管理
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
// 方式2:收集一次性事件
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.events.collect { event ->
handleEvent(event)
}
}
}
}
private fun updateUI(state: UiState) {
when (state) {
is UiState.Loading -> {
showLoading()
hideError()
hideContent()
}
is UiState.Success -> {
hideLoading()
hideError()
showContent(state.data)
}
is UiState.Error -> {
hideLoading()
showError(state.message)
hideContent()
}
}
}
// 安全收集(防止重复订阅)
private fun collectFlows() {
collectJob?.cancel() // 取消之前的收集
collectJob = lifecycleScope.launch {
launch {
viewModel.uiState.collect { updateUI(it) }
}
launch {
viewModel.events.collect { handleEvent(it) }
}
}
}
}
4.3 Repository层的Flow封装
class UserRepository(
private val api: UserApi,
private val dao: UserDao,
private val networkManager: NetworkManager
) {
// 网络 + 数据库的完整Flow
fun getUsersWithCache(): Flow<List<User>> = networkManager.isConnected
.flatMapLatest { isConnected ->
if (isConnected) {
// 有网络:从网络获取并缓存
flow {
val users = api.getUsers()
dao.insertAll(users)
emit(users)
}
.catch { error ->
// 网络失败时从数据库读取
emitAll(dao.getAllUsersFlow())
}
} else {
// 无网络:从数据库读取
dao.getAllUsersFlow()
}
}
.flowOn(Dispatchers.IO)
// 实时搜索(支持防抖、缓存)
fun searchUsers(query: String): Flow<List<User>> = flow {
// 先从本地缓存搜索
val cached = dao.searchUsers("%$query%")
if (cached.isNotEmpty()) {
emit(cached)
}
// 然后从网络搜索并更新缓存
val remote = api.searchUsers(query)
dao.insertAll(remote)
emit(remote)
}
.distinctUntilChanged() // 相同结果不重复发射
.flowOn(Dispatchers.IO)
}
五、Flow vs LiveData vs RxJava 全面对比
| 特性 | LiveData | Kotlin Flow | RxJava |
|---|---|---|---|
| 生命周期感知 | 原生支持 | 需结合repeatOnLifecycle | 需额外处理 |
| 协程集成 | 不支持 | 完美集成 | 需要适配器 |
| 线程切换 | 需postValue | 自动调度器 | 调度器支持 |
| 冷流/热流 | 只有热流 | 两者都支持 | 两者都支持 |
| 错误处理 | 困难 | 完善的catch | 完善的错误处理 |
| 背压处理 | 不支持 | buffer操作符 | 多种策略 |
六、最佳实践与性能优化
6.1 性能优化技巧
class FlowPerformanceTips {
// 1. 使用合适的buffer
fun withBuffer() {
fastProducerFlow
.buffer(capacity = 64) // 避免背压
.collect { value ->
slowConsumer(value) // 慢消费者
}
}
// 2. 避免不必要的collect
fun avoidUnnecessaryCollect() {
// 错误:多次collect创建多个Flow
val flow = getDataFlow()
flow.collect { } // 第一次
flow.collect { } // 第二次(重新执行生产者)
// 正确:共享Flow
val sharedFlow = getDataFlow().shareIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
replay = 1
)
}
// 3. 使用flowOn切换上下文
fun properContextSwitching() {
dataFlow
.map { it * 2 } // 在IO线程执行
.flowOn(Dispatchers.IO)
.filter { it > 10 } // 回到默认线程
.collect { } // 在主线程收集
}
// 4. 避免内存泄漏
class SafeFlowCollector : DefaultLifecycleObserver {
private var collectionJob: Job? = null
override fun onStart(owner: LifecycleOwner) {
collectionJob = viewModelScope.launch {
dataFlow.collect { data ->
updateUI(data)
}
}
}
override fun onStop(owner: LifecycleOwner) {
collectionJob?.cancel()
}
}
}
6.2 常见陷阱与解决方案
| 陷阱 | 现象 | 解决方案 |
|---|---|---|
| 忘记取消收集 | 内存泄漏,后台继续执行 | 使用lifecycleScope + repeatOnLifecycle |
| 多次collect导致重复执行 | 网络请求重复发送 | 使用stateIn/shareIn共享Flow |
| UI线程阻塞 | 界面卡顿 | 使用flowOn(Dispatchers.IO) |
| 背压导致数据丢失 | 快速发射的数据被丢弃 | 使用.buffer()操作符 |
| 异常未被捕获 | 应用崩溃 | 使用.catch {}操作符 |
| 热流冷流混淆 | 预期外的行为 | 明确区分Flow和StateFlow/SharedFlow |
七、Flow高级应用场景
7.1 实时聊天应用
class ChatRepository {
// 消息Flow:合并本地和远程
fun getMessages(chatId: String): Flow<List<Message>> {
return merge(
getLocalMessages(chatId),
getRemoteMessages(chatId)
).scan(emptyList()) { acc, newMessages ->
(acc + newMessages).distinctBy { it.id }
}
}
// 输入防抖 + 发送
fun setupMessageSending(inputFlow: Flow<String>) {
inputFlow
.debounce(1000) // 输入暂停1秒后发送
.filter { it.isNotBlank() }
.mapLatest { text ->
sendMessage(text) // 发送消息
text // 清空输入框
}
.catch { error ->
showError("发送失败")
}
.launchIn(viewModelScope)
}
}
7.2 分页加载
class PagingWithFlow {
fun loadItemsPaged(): Flow<PagingData<Item>> = Pager(
config = PagingConfig(
pageSize = 20,
enablePlaceholders = false,
initialLoadSize = 40
),
pagingSourceFactory = { ItemPagingSource(api) }
).flow
.map { pagingData ->
// 转换数据
pagingData.map { item ->
ItemUiModel(item)
}
}
.cachedIn(viewModelScope) // 缓存到ViewModel生命周期
}
7.3 实时表单验证
class FormValidation {
fun validateForm(
emailFlow: Flow<String>,
passwordFlow: Flow<String>
): Flow<FormState> {
return combine(emailFlow, passwordFlow) { email, password ->
val emailValid = isValidEmail(email)
val passwordValid = isValidPassword(password)
FormState(
emailError = if (emailValid) null else "Invalid email",
passwordError = if (passwordValid) null else "Too short",
isValid = emailValid && passwordValid
)
}
.distinctUntilChanged() // 只有状态变化时发射
}
}
总结
Kotlin Flow代表了Android响应式编程的未来方向:
核心优势
- 与协程完美集成:统一的并发模型
- 声明式API:代码更简洁易读
- 完善的异常处理:安全的错误传播机制
- 灵活的冷热流:适应各种场景需求
- 优秀的性能:轻量级,低开销
适用场景
- UI状态管理(StateFlow)
- 一次性事件处理(SharedFlow)
- 实时数据流(网络推送、传感器数据)
- 复杂的异步数据转换
- 需要取消和资源管理的场景
作者:许丽雯
原文链接:Kotlin Flow:构建响应式数据流的完整指南
1585

被折叠的 条评论
为什么被折叠?



