Kotlin Flow 常用用法指南

Kotlin Flow 常用用法指南

Kotlin Flow 是基于协程的异步流,用于按顺序发出多个值。以下是项目中常用的 Flow 操作与模式总结。

1. 创建 Flow

常用的创建方式包括 flow 构建器、flowOf 和扩展函数 asFlow

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 使用 flow {} 构建器
val simpleFlow = flow {
for (i in 1..3) {
delay(100)
emit(i) // 发送值
}
}

// 2. 使用 flowOf() 发送固定值
val fixedFlow = flowOf("A", "B", "C")

// 3. 将集合或序列转换为 Flow
val collectionFlow = listOf(1, 2, 3).asFlow()

2. 末端操作符 (Terminal Operators)

末端操作符会触发 Flow 的收集。

  • collect: 最基础的收集操作。
  • toList / toSet: 将 Flow 转换为集合。
  • first: 获取第一个值(并取消后续发送)。
  • reduce / fold: 对流中的值进行累加计算。
1
2
val sum = (1..5).asFlow()
.reduce { a, b -> a + b } // 结果为 15

3. 中间操作符 (Intermediate Operators)

用于对流进行变换,它们是冷操作符,不会立即触发执行。

  • map: 转换每个值。
  • filter: 过滤值。
  • transform: 最通用的变换操作符,可以多次调用 emit
  • take: 限制发送数量。
1
2
3
4
5
(1..10).asFlow()
.filter { it % 2 == 0 }
.map { "Number $it" }
.take(2)
.collect { println(it) } // 输出 Number 2, Number 4

4. 线程切换 (flowOn)

Flow 遵循上下文保存原则。使用 flowOn 改变上游操作符执行的协程上下文。

1
2
3
4
5
6
7
8
flow {
// 这部分将运行在 Dispatchers.Default
emit(computeResult())
}.flowOn(Dispatchers.Default)
.collect { value ->
// 这部分运行在收集器的上下文中(如 Dispatchers.Main)
updateUI(value)
}

5. 背压处理 (Buffering & Conflation)

当生产者速度快于消费者时,可以使用以下方式:

  • buffer(): 缓冲发送,让生产者和消费者并发运行。
  • conflate(): 合并发送,消费者只处理最新的值,跳过中间值。
  • collectLatest: 当有新值发出时,取消当前的收集处理并开始处理新值。
1
2
3
4
5
6
simpleFlow()
.buffer() // 并发处理,提高效率
.collect { value ->
delay(300)
println(value)
}

6. 组合多个 Flow

  • zip: 一对一合并两个流的值。
  • combine: 只要任何一个流发出新值,就使用两个流最新的值进行合并计算。
1
2
3
val nums = (1..3).asFlow()
val strs = flowOf("One", "Two", "Three")
nums.zip(strs) { a, b -> "$a -> $b" }.collect { println(it) }

7. 展平流 (Flattening)

当流的值本身也是流时(Flow<Flow<T>>):

  • flatMapConcat: 按顺序连接(等待前一个内部流完成)。
  • flatMapMerge: 并发合并内部流。
  • flatMapLatest: 只要外部流发出新值,就取消前一个内部流的收集。

8. 异常处理与完成

  • catch: 捕获上游抛出的异常。
  • onCompletion: 在流完成(无论正常还是异常)时执行。
1
2
3
4
simpleFlow()
.onCompletion { cause -> println("Done with $cause") }
.catch { e -> emit(-1) } // 捕获异常并发送默认值
.collect { println(it) }
,