我有一个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
}
}
有什么改善建议吗?预先感谢!
答案 0 :(得分:0)
您可以使用Kotlin的扩展功能使它更具反应性。
假设您拥有firstLiveaData
和secondLiveData
且具有相同类型的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
扩展功能。