带有多个参数的 LiveData Transformations.map() [英] LiveData Transformations.map() with multiple arguments

查看:43
本文介绍了带有多个参数的 LiveData Transformations.map()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆