提问人:Alele 提问时间:11/1/2023 更新时间:11/2/2023 访问量:58
如何在视图模型的 init 块中包含合并的流
How to include a merged flow in init block of viewmodel
问:
我在 init 块中编写了代码,该代码合并了 4 个流 () 并输出一个修改 值的单个流。问题在于,当 4 个流中的任何一个发生变化时,的值不会改变。为什么_totalAmount的价值没有改变?运行代码时没有错误。merge(periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd)
_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)
提出问题的原因
我有几个变量取决于 ,这 4 个流程。我不想像上面那样继续声明变量。我想要像下面的代码一样的东西periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd
totalAmount
例
这是我想实现的一个例子。
merge(periodStart, periodEnd, selectedPeriodStart, selectedPeriodEnd).map{
val a = {...}
val b = {...}
val c = {...}
...
}
如果您需要任何澄清,请询问。
答:
我认为对于这个用例,一个更好的运算符是组合所有流的值并根据需要使用它们(更改多个变量或其他流的值)。您可以在此处阅读有关它及其差异的更多信息:combine
combine
merge
我已经测试过了:
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
我用过,但你也可以用,这取决于你的用例。collectLatest
collect
尽管我已经对此进行了测试并且它正在工作,但我不知道直接从 ViewModel 的块中收集此组合流是否是一种好做法,也许将其放在变量中只是为了确保您可以在需要时轻松取消它。init
Job
我会更深入地研究这部分,如果这真的是值得担心的事情,也许有人可以补充。
评论