Kotlin中的Flow流

109 阅读3分钟

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 (普通冷流)

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

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

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

它是 LiveData 的现代替代品。

  • 特点:始终持有最新的一个状态值。新的收集者加入时,会立刻收到当前最新的值。
  • 场景:用于存储 UI 状态(如:Loading、Success、Error)。
  • 对比 LiveDataStateFlow 必须有初始值,且完全支持协程操作符。
// 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、服务器推送消息。
// 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)时自动取消协程,停止接收数据。

// 在 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,并感知生命周期。

@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 线程执行)