进阶变换:Scan 与 Reduce
Scan 和 Reduce 都是“累加”操作,但一个是过程中的变换,一个是最终的结论。
过程累计:scan (runningFold)
scan 会发射每一次累加的结果。
- 输入: 1, 2, 3
- scan(0) { acc, v -> acc + v }
- 输出: 0 (初始值), 1 (0+1), 3 (1+2), 6 (3+3)
kotlin
// 场景:实时显示下载总进度
chunkFlow.scan(0) { loaded, newChunk ->
loaded + newChunk.size
}.collect { total ->
updateProgressBar(total)
}终局汇总:reduce 与 fold
这两个操作符会挂起流的收集,直到上游流结束,只返回一个最终结果。
| 操作符 | 初始值 | 空流行为 |
|---|---|---|
fold | 必须指定 | 返回初始值 |
reduce | 无 (取第1个元素) | 抛出异常 (NoSuchElementException) |
订阅者计数:subscriptionCount
对于 SharedFlow 和 StateFlow,subscriptionCount 是一个特殊的 StateFlow<Int>,虽然它不是操作符,但常配合操作符使用。
实战:自动保活与停止
kotlin
// 当且仅当有 UI 订阅时,才开启底层的定位服务
locationFlow
.subscriptionCount
.map { count -> count > 0 }
.distinctUntilChanged()
.collect { hasSubscribers ->
if (hasSubscribers) startGps() else stopGps()
}