首页 > 解决方案 > “合并”数据或“设置”数据,MediatorLiveData

问题描述

文档(https://developer.android.com/reference/androidx/lifecycle/MediatorLiveData)谈论合并数据......但功能显然是设置它。

当我考虑“合并”时,我会想到诸如 .add() 或 .put() 或 .set(X x, Y y),.. 之类的东西,我可以将 2 个对象捆绑在一个中,或者一个列表对象或对象数组。

但是函数说.setValue(),文档说合并

在此处输入图像描述

日志给我的印象是前 2 个 setValue() 被完全忽略:

在此处输入图像描述

所以不是:

   ViewModel: onChnaged: [Folder1, Folder2, Folder3]
   Fragment: onChanged: Folder1 ...etc
   ViewModel: onChanged: []
   Fragment: onChanged:
   ViewModel: onChanged: [Quantity1, Quantity2, Quantity3]
   Fragment: onChanged: Quantity1 ...etc

只有第一个 .setValue(folders) 显示在 Fragment 上,我猜这只是因为它在 3 个要解决的查询中花费的时间最长。

MediatorLiveData

……

在此处输入图像描述

因此,如果我对合并的概念有误,我需要在其中使用 Diff.Util 执行 LiveData/MutableLiveData<List<?>> 来管理传入列表或单个对象以及处理异步时间的信号量( ?也许?)..和一个 .add() 和 .replace() 函数相应地,等等...,但是我可以使用任何 LiveData,而不是 MediatorLiveData<>。

有什么我可以用的吗?

我错过了什么?

最糟糕的是,如果 MediatorLiveData 像我认为的那样做,那么在正确处理其生命周期的同时将多个 LiveData 连接到单个观察者真的不难......重点是什么。

我看到一些使用 .combine(data1, data2) 的 Kotlin 示例,但该函数甚至不存在。

标签: javaandroid-livedatamediatorlivedata

解决方案


这个答案在kotlin,希望你能看懂或者有人能翻译成java。我有这个扩展,它将 3 个 livedata 源组合到一个对象中。

扩大:

fun <T, A, B, C> LiveData<A>.combineAndCompute3(
    other1: LiveData<B>,
    other2: LiveData<C>,
    onChange: (A, B?, C?) -> T
): LiveData<T> {

    var source0emitted = false
    var source1emitted = false
    var source2emitted = false

    val result = MediatorLiveData<T>()

    val mergeF = {
        val source0Value = this.value
        val source1Value = other1.value
        val source2Value = other2.value

        if (source0emitted && source1emitted && source2emitted) {
            result.value = onChange.invoke(source0Value!!, source1Value, source2Value)
        }
    }

    result.addSource(this) { source0emitted = true; mergeF.invoke() }
    result.addSource(other1) { source1emitted = true; mergeF.invoke() }
    result.addSource(other2) { source2emitted = true; mergeF.invoke() }

    return result
}

在我的视图模型中,我有这样的:


    private val _id = MutableLiveData<Int>()
    private val id = _id.distinctUntilChanged()

    private val _name = MutableLiveData<String?>()
    private val name = _name.distinctUntilChanged()

    private val _load = MutableLiveData<Boolean>()
    private val load = _load.distinctUntilChanged()


    private val detailLoad = id.combineAndCompute3(name, load) {
        A, B, C -> DetailLoad(A, B, C)
    }

DetailLoad 是一个常规数据类,A 是一个整数,B 是一个字符串,C 是一个布尔值,我以非常标准的方式将值 postValue 到我的 mutablelivedatas 中。


推荐阅读