带有多个参数的 LiveData Transformations.map() [英] LiveData Transformations.map() with multiple arguments
问题描述
我在 UI 中有一个值,它的值取决于两个 LiveData 对象.想象一下你需要一个subtotal = sum of all items price
和一个total = subtotal + shipping price
的商店.使用 Transformations 我们可以对小计 LiveData 对象执行以下操作(因为它只取决于 itemsLiveData
):
I have a value in the UI that it's value depends on two LiveData objects. Imagine a shop where you need a subtotal = sum of all items price
and a total = subtotal + shipment price
. Using Transformations we can do the following for the subtotal LiveData object (as it only depends on itemsLiveData
):
val itemsLiveData: LiveData<List<Items>> = ...
val subtotalLiveData = Transformations.map(itemsLiveData) {
items ->
getSubtotalPrice(items)
}
就总数而言,能够做这样的事情会很棒:
In the case of the total it would be great to be able to do something like this:
val shipPriceLiveData: LiveData<Int> = ...
val totalLiveData = Transformations.map(itemsLiveData, shipPriceLiveData) {
items, price ->
getSubtotalPrice(items) + price
}
但是,不幸的是,这是不可能的,因为我们不能在 map 函数中放置多个参数.有人知道实现这一目标的好方法吗?
But, unfortunately, that's not possible because we cannot put more than one argument in the map function. Anyone knows a good way of achieving this?
推荐答案
UPDATE
基于我之前的回答,我创建了一种通用方式,我们可以根据需要添加任意数量的实时数据.
Based on my previous answer, I created a generic way where we can add as many live datas as we want.
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
/**
* CombinedLiveData is a helper class to combine results from multiple LiveData sources.
* @param liveDatas Variable number of LiveData arguments.
* @param combine Function reference that will be used to combine all LiveData data.
* @param R The type of data returned after combining all LiveData data.
* Usage:
* CombinedLiveData<SomeType>(
* getLiveData1(),
* getLiveData2(),
* ... ,
* getLiveDataN()
* ) { datas: List<Any?> ->
* // Use datas[0], datas[1], ..., datas[N] to return a SomeType value
* }
*/
class CombinedLiveData<R>(vararg liveDatas: LiveData<*>,
private val combine: (datas: List<Any?>) -> R) : MediatorLiveData<R>() {
private val datas: MutableList<Any?> = MutableList(liveDatas.size) { null }
init {
for(i in liveDatas.indices){
super.addSource(liveDatas[i]) {
datas[i] = it
value = combine(datas)
}
}
}
}
旧
最后,我使用 MediatorLiveData 来实现相同的目标.
At the end I used MediatorLiveData to achieve the same objective.
fun mapBasketTotal(source1: LiveData<List<Item>>, source2: LiveData<ShipPrice>): LiveData<String> {
val result = MediatorLiveData<String>()
uiThread {
var subtotal: Int = 0
var shipPrice: Int = 0
fun sumAndFormat(){ result.value = format(subtotal + shipPrice)}
result.addSource(source1, { items ->
if (items != null) {
subtotal = getSubtotalPrice(items)
sumAndFormat()
}
})
result.addSource(source2, { price ->
if (price != null) {
shipPrice = price
sumAndFormat()
}
})
}
return result
}
这篇关于带有多个参数的 LiveData Transformations.map()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!