Kotlin中的Flow流

Kotlin Flow 是 Android 开发中推荐的异步数据流 解决方案。它基于 Kotlin 协程(Coroutines)构建,功能强大且灵活,旨在替代 RxJava 和部分 LiveData 的使用场景。

我们可以把它理解成一个管道:

上游(Upstream) :负责生产数据(如:从数据库读数据、网络请求)。

中游(Intermediaries) :负责处理数据(如:过滤 filter、转换 map)。

下游(Downstream) :负责接收/消费数据(如:更新 UI)。

核心概念: 冷流VS热流

特性 Cold Flow (普通 Flow) Hot Flow (StateFlow / SharedFlow)
激活时机 只有被收集(collect)时才开始运行。 无论有无收集者,它都在内存中活跃(类似于 LiveData)。
数据生产 是一对一的(Unicast)。每个收集者都会触发一遍新的数据生产流程。 是一对多的(Multicast)。多个收集者共享同一个数据源。
典型场景 耗时的数据库读取、文件下载、简单的异步转换。 UI 状态管理 (StateFlow)、一次性事件 (SharedFlow)。

具体例子:

A. Flow (普通冷流)

最基础的类型。用于执行耗时任务并按顺序发射多个值。

kotlin 复制代码
// 例子:倒计时
fun countdownFlow(): Flow<Int> = flow {
    for (i in 5 downTo 0) {
        emit(i) // 发射数据
        delay(1000) // 挂起函数,不阻塞线程
    }
}

B. StateFlow (热流 - 状态持有者)

它是 LiveData 的现代替代品。

  • 特点 :始终持有最新的一个状态值。新的收集者加入时,会立刻收到当前最新的值。
  • 场景:用于存储 UI 状态(如:Loading、Success、Error)。
  • 对比 LiveDataStateFlow 必须有初始值,且完全支持协程操作符。
kotlin 复制代码
// ViewModel 中
private val _uiState = MutableStateFlow("Initial State")
val uiState: StateFlow<String> = _uiState.asStateFlow()
​
// 更新状态
_uiState.value = "New State"

C. SharedFlow (热流 - 事件流)

  • 特点 :用于发送一次性事件 (One-off events)。默认不保留旧数据(除非配置 replay),新收集者不会收到过去发出的事件。
  • 场景:导航跳转、弹出 Toast、显示 Snackbar、服务器推送消息。
arduino 复制代码
// ViewModel 中
private val _events = MutableSharedFlow<String>()
val events: SharedFlow<String> = _events.asSharedFlow()
​
// 发送事件 (suspend function)
_events.emit("Show Toast")

在UI中安全收集

a. 在 Activity / Fragment (使用 Views)

使用 repeatOnLifecycle。它会在特定的生命周期状态(通常是 STARTED)开始收集,在低于该状态(如后台 STOPPED)时自动取消协程,停止接收数据。

javascript 复制代码
// 在 Activity 或 Fragment 中
lifecycleScope.launch {
    // 只有当生命周期至少是 STARTED 时才执行块内代码
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        // 这两个流会并行收集
        launch {
            viewModel.uiState.collect { state ->
                // 更新 UI
            }
        }
        launch {
            viewModel.events.collect { event ->
                // 处理事件
            }
        }
    }
}

b. compose

使用 collectAsStateWithLifecycle()。它会自动将 Flow 转换为 Compose 的 State,并感知生命周期。

kotlin 复制代码
@Composable
fun MyScreen(viewModel: MyViewModel) {
    // 需要引入依赖: androidx.lifecycle:lifecycle-runtime-compose
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    
    Text(text = state)
}

常用操作符

转换类map (数据映射), transform (自定义转换)

过滤类filter (过滤), debounce (防抖,搜索框必备), distinctUntilChanged (防重复,StateFlow 默认自带此特性)

组合类combine (合并多个流), zip, flatMapLatest (切换流,例如搜索词变化时取消旧请求发新请求)

异常处理catch (捕获上游异常)

线程切换flowOn(Dispatchers.IO) (指定上游代码在 IO 线程执行)

相关推荐
TA远方1 小时前
【Android】adb常用的命令用法详解
android·adb·管理·控制·命令
贺biubiu9 小时前
2025 年终总结|总有那么一个人,会让你千里奔赴...
android·程序员·年终总结
xuekai200809019 小时前
mysql-组复制 -8.4.7 主从搭建
android·adb
资生算法程序员_畅想家_剑魔9 小时前
Kotlin常见技术分享-02-相对于Java 的核心优势-协程
java·开发语言·kotlin
nono牛10 小时前
ps -A|grep gate
android
未知名Android用户11 小时前
Android动态变化渐变背景
android
nono牛12 小时前
Gatekeeper 的精确定义
android
stevenzqzq13 小时前
android启动初始化和注入理解3
android
城东米粉儿15 小时前
compose 状态提升 笔记
android
粤M温同学16 小时前
Android 实现沉浸式状态栏
android