Skip to content

进阶变换: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

对于 SharedFlowStateFlowsubscriptionCount 是一个特殊的 StateFlow<Int>,虽然它不是操作符,但常配合操作符使用。

实战:自动保活与停止

kotlin
// 当且仅当有 UI 订阅时,才开启底层的定位服务
locationFlow
    .subscriptionCount
    .map { count -> count > 0 }
    .distinctUntilChanged()
    .collect { hasSubscribers ->
        if (hasSubscribers) startGps() else stopGps()
    }