将两个状态流组合成新的状态流

Kir*_*ach 20 collections kotlin kotlin-flow

我有两个状态流。是否有可能将它们结合起来并获得新的状态流?从逻辑上讲,这应该是可能的,因为两个状态流都有初始值,但正如我所见,组合函数仅返回 Flow 而不是 StateFlow。

Mer*_*gic 23

您可以使用combine运算符,然后将stateIn函数用于Flow由此产生的结果。

来自kotlinx 协程存储库中的stateIn 文档:

stateIn函数“将冷量 Flow转换为在给定协程范围内启动的热量 StateFlow,与多个下游订阅者共享上游流的单个运行实例中最近发出的值。”

截至撰写本文时,其签名为:

fun <T> Flow<T>.stateIn(
  scope: CoroutineScope,
  started: SharingStarted,
  initialValue: T
): StateFlow<T> (source)
Run Code Online (Sandbox Code Playgroud)

因此,您应该能够对Flows 进行所需的任何转换,包括将它们组合起来,然后最终用于stateIn将它们转换回StateFlow.

它可能看起来像这样(也许创建一个拼字游戏游戏点数计算器):

val wordFlow = MutableStateFlow("Hi")
val pointFlow = MutableStateFlow(5)

val stateString = wordFlow.combine(pointFlow) { word, points ->
    "$word is worth $points points"
}.stateIn(viewModelScope, SharingStarted.Eagerly, "Default is worth 0 points")
Run Code Online (Sandbox Code Playgroud)

stateString将是一种类型StateFlow<String>,并且您已成功地将另外两个StateFlows合二为一StateFlow


Kir*_*ach 6

到目前为止我创建了函数:

fun <T1, T2, R> combineState(
        flow1: StateFlow<T1>,
        flow2: StateFlow<T2>,
        scope: CoroutineScope = GlobalScope,
        sharingStarted: SharingStarted = SharingStarted.Eagerly,
        transform: (T1, T2) -> R
): StateFlow<R> = combine(flow1, flow2) {
    o1, o2 -> transform.invoke(o1, o2)
}.stateIn(scope, sharingStarted, transform.invoke(flow1.value, flow2.value))
Run Code Online (Sandbox Code Playgroud)