kotlin 如何在视图模型的init块中包含合并流

ufj5ltwl  于 2023-11-21  发布在  Kotlin
关注(0)|答案(1)|浏览(118)

我已经在init块中编写了合并4个流(merge(periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd))并输出一个修改_totalAmount值的流的代码。问题是,当4个流中的任何一个改变时,_totalAmount的值都不会改变。为什么_totalAmount的值没有改变?运行代码时没有错误。

_totalAmount的值不变

val _totalAmount = MutableStateFlow(0)
val totalAmount = _totalAmount.asStateFlow()

init{    
        merge(periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd)
            .map{                
                withContext(Dispatchers.IO){
                    _totalAmount.value = soldItemRepo.getTotalAmountSoldPerPeriod(
                        periodStart.value ?: selectedPeriodStart.value,
                        periodEnd.value ?: selectedPeriodEnd.value
                    ).first()
                }
            }
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS),
                initialValue = 0
            )
    }

字符串
我知道,如果我在视图模型的主体中包含合并的流,如下图所示,那么每当4个流中的任何一个发生变化时,_totalAmount的值都会发生变化。

totalAmount的值发生变化

val totalAmount = merge(periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd)
        .map{
            withContext(Dispatchers.IO){
                soldItemRepo.getTotalAmountSoldPerPeriod(
                    periodStart.value ?: selectedPeriodStart.value,
                    periodEnd.value ?: selectedPeriodEnd.value
                ).first()
            }
        }.stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS),
            initialValue = 0)

问问题的原因

我有几个变量依赖于periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd,4流。我不想继续声明变量,因为我已经在上面的totalAmount的情况下。我想有类似下面的代码

示例

这是我想要实现的一个例子。

merge(periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd).map{
val a = {...}
val b = {...}
val c = {...}
...
}


如果你需要任何解释,尽管问。

2wnc66cl

2wnc66cl1#

我认为对于这个用例来说,一个更好的操作符是combine,它可以合并组合所有流的值,并根据需要使用它们(更改多个变量的值,或其他流)。你可以阅读更多关于combine的信息,以及它和mergehere之间的区别:
我测试过这个:

val unitsFlow = MutableStateFlow(0)
    val tensFlow = MutableStateFlow(0)
    val hundredsFlow = MutableStateFlow(0)

    private var a = 0
    private var b = 0
    private var c = 0
    private val exampleFlow = MutableStateFlow(0)

    init {
        viewModelScope.launch {
            combine(unitsFlow, tensFlow, hundredsFlow) { units, tens, hundreds ->
                Triple(units, tens, hundreds) // just concatenate the most recent values (no transformation)
            }.collectLatest { (units, tens, hundreds) ->
                // update several variables (or other flows) using the most recent values
                a = units * 1
                b = (units * 1) + (tens * 10)
                c = (units * 1) + (tens * 10) + (hundreds * 100)
                exampleFlow.update { a + b + (hundreds * 2) }
            }
        }
    }

字符串
我已经使用了一些随机变量和流来说明你想要的东西。因为你只想合并组合几个流而不转换它们的值,combine部分只是简单地把它们放在一起,在一个Triple中,我不确定你是否可以跳过这个样板部分,但some people have tackled this issue
我已经使用了collectLatest,但你也可以使用collect,这取决于你的用例。
尽管我已经测试过了,而且它是有效的,但我不知道直接从ViewModel的init块中收集这个组合流是否是一个好的做法,也许把它放在一个Job变量中,只是为了确保你可以在需要时轻松地取消它。
我会更深入地研究这一部分,也许有人可以补充,如果这真的是值得担心的事情。

相关问题