每当其他LiveData之一更新其值时更新LiveData的值

时间:2019-04-23 09:36:10

标签: android android-livedata

我有一个LiveData,其中包含这样的列表:

val originalSourceLiveaData = MutableLiveData<List<SomeType>>()

现在我还有另一个LiveData,它应该指示对originalSourceLiveaData值的过滤。

val filterLiveData = MutableLiveData<String>()

我想要的是,每次LiveData中的任何一个更改值时,都应更新结果列表。我试图做这样的事情:

val filteredListLiveData = MediatorLiveData<List<SomeType>().apply {
    addSource(originalSourceLiveaData) { this.value = filteringMethod() }
    addSource(filterLiveData) { this.value = filteringMethod() }
}

这很好,但是我想知道是否有更好的解决方案。

我的问题是,如果添加了另一个LiveData,则必须像这样添加它作为源:

val filteredListLiveData = MediatorLiveData<List<SomeType>().apply {
    addSource(originalSourceLiveaData) { this.value = filteringMethod() }
    addSource(filterLiveData) { this.value = filteringMethod() }
    addSource(anotherSourceLiveData) { 
        this.value = filteringMethod() // this feels like a duplicate 
    }
}

有什么改善建议吗?预先感谢!

1 个答案:

答案 0 :(得分:0)

您可以使用Kotlin的扩展功能使它更具反应性。

假设您拥有firstLiveaDatasecondLiveData且具有相同类型的T。现在,您要先过滤它们,然后再听所有更改。

因此,您可以添加以下扩展功能:

  • filter函数将根据给定的谓词函数过滤您的实时数据
  • addSources函数将完成添加多个实时数据并收听其更改的样板
fun <T> LiveData<T>.filter(predicate : (T) -> Boolean): LiveData<T> {
    val mutableLiveData = MediatorLiveData<T>()
    mutableLiveData.addSource(this) {
        if(predicate(it))
            mutableLiveData.value = it
    }
    return mutableLiveData
}

fun <T> MediatorLiveData<T>.addSources(vararg listOfLiveData: LiveData<T>, callback: (T) -> Unit) {
    listOfLiveData.forEach {
        addSource(it, callback)
    }
}

此外,您可以使用LivaData函数将多个具有相同类型的merge对象合并为一个对象:

fun <T> merge(vararg liveDataList: LiveData<T>): LiveData<T> {
    val mergedLiveData = MediatorLiveData<T>()
    liveDataList.forEach { liveData ->

        liveData.value?.let {
            mergedLiveData.value = it
        }

        mergedLiveData.addSource(liveData) { source ->
            mergedLiveData.value = source
        }
    }
    return mergedLiveData
}

这里是一个例子:

fun doSomething() {
    val firstLiveData = MutableLiveData<List<SomeType>>()
    val secondLiveData = MutableLiveData<List<SomeType>>()

    merge(firstLiveData, secondLiveData).filter { someFilterFunction() }.observe(...)
}

如果您使用其他类型的LiveData(例如firstLiveData<Int>secondLiveData<String>),则可以简单地添加一个map扩展功能。