我正在尝试将3个或更多LiveData作为源进行通用合并,其中每个LiveData的通用类型均与其他LiveData不同。为此,我的目的是使用每个LiveData接收的vararg及其各自的类型。
我已经解决了这个问题,但是为3个数据源提供了一个“硬编码”,其解决方案与此answer的解决方案非常相似,但是它不可伸缩。
fun getSourceR(): MutableLiveData<Object_R>() {}
fun getSourceS(): MutableLiveData<Object_S>() {}
fun getSourceU(): MutableLiveData<Object_U>() {}
MergeLiveDataTest(getSourceR(), getSourceS(), getSourceU()) {
sources ->
Log.d("MergeLiveData", sources[0].value.methodOf_R)
Log.d("MergeLiveData", sources[1].value.methodOf_S)
Log.d("MergeLiveData", sources[2].value.methodOf_U)
}
问题:我无法访问源类型对象的方法。
我想做的是使循环X的每个迭代为R,S或U。
class MergeLiveDataTest<T, X>(
vararg sources: LiveData<X>,
private val onChanged: (newData: MutableList<LiveData<X>>) -> T
) : MediatorLiveData<T>() {
private lateinit var _sources: MutableList<LiveData<X>>
init {
for (i in sources.indices) {
super.addSource(sources[i]) {
_sources.add(i, sources[i])
value = onChanged(_sources)
}
}
}
}
有任何建议吗?谢谢
我已经解决了这个问题,但是为3个数据源提供了一个“硬编码”,其解决方案与该答案非常相似,但这是不可扩展的。
当然是,您没看过EDIT吗? ;)
您可以使用具有相同功能的库https://github.com/Zhuinden/livedata-combinetuple-kt。
现在仅链接的答案不是一件好事,所以我将解释它的作用。
首先,我有一个4-16的元组(因为Kotlin在Pair
中已经具有Triple
和tuples-kt)
它们看起来像这样:
data class Tuple4<A, B, C, D>( val first: A, val second: B, val third: C, val fourth: D ) : Serializable { override fun toString(): String { return "Tuple4[$first, $second, $third, $fourth]" } } data class Tuple5<A, B, C, D, E>( val first: A, val second: B, val third: C, val fourth: D, val fifth: E ) : Serializable { override fun toString(): String { return "Tuple5[$first, $second, $third, $fourth, $fifth]" } }
然后在LiveData-CombineTuple-KT
中,有这样的代码:
fun <T1, T2, T3, T4> combineTuple(f1: LiveData<T1>, f2: LiveData<T2>, f3: LiveData<T3>, f4: LiveData<T4>): LiveData<Tuple4<T1?, T2?, T3?, T4?>> = MediatorLiveData<Tuple4<T1?, T2?, T3?, T4?>>().also { mediator ->
mediator.value = Tuple4(f1.value, f2.value, f3.value, f4.value)
mediator.addSource(f1) { t1: T1? ->
val (_, t2, t3, t4) = mediator.value!!
mediator.value = Tuple4(t1, t2, t3, t4)
}
mediator.addSource(f2) { t2: T2? ->
val (t1, _, t3, t4) = mediator.value!!
mediator.value = Tuple4(t1, t2, t3, t4)
}
mediator.addSource(f3) { t3: T3? ->
val (t1, t2, _, t4) = mediator.value!!
mediator.value = Tuple4(t1, t2, t3, t4)
}
mediator.addSource(f4) { t4: T4? ->
val (t1, t2, t3, _) = mediator.value!!
mediator.value = Tuple4(t1, t2, t3, t4)
}
}
fun <T1, T2, T3, T4, T5> combineTuple(f1: LiveData<T1>, f2: LiveData<T2>, f3: LiveData<T3>, f4: LiveData<T4>, f5: LiveData<T5>): LiveData<Tuple5<T1?, T2?, T3?, T4?, T5?>> = MediatorLiveData<Tuple5<T1?, T2?, T3?, T4?, T5?>>().also { mediator ->
mediator.value = Tuple5(f1.value, f2.value, f3.value, f4.value, f5.value)
mediator.addSource(f1) { t1: T1? ->
val (_, t2, t3, t4, t5) = mediator.value!!
mediator.value = Tuple5(t1, t2, t3, t4, t5)
}
mediator.addSource(f2) { t2: T2? ->
val (t1, _, t3, t4, t5) = mediator.value!!
mediator.value = Tuple5(t1, t2, t3, t4, t5)
}
mediator.addSource(f3) { t3: T3? ->
val (t1, t2, _, t4, t5) = mediator.value!!
mediator.value = Tuple5(t1, t2, t3, t4, t5)
}
mediator.addSource(f4) { t4: T4? ->
val (t1, t2, t3, _, t5) = mediator.value!!
mediator.value = Tuple5(t1, t2, t3, t4, t5)
}
mediator.addSource(f5) { t5: T5? ->
val (t1, t2, t3, t4, _) = mediator.value!!
mediator.value = Tuple5(t1, t2, t3, t4, t5)
}
}
从3到16一直写。尽管它是Kotlin库,所以假定您的项目中有Pair
和Triple
的Kotlin-stdlib。
无论如何,我认为将16个LiveData组合成一个元组的能力对于大多数情况来说应该足够了。
如果不允许Kotlin,那么我确定相关的Kotlin逻辑可以翻译成Java,但是它会更加冗长,所以我从来没有这样做。
在Kotlin中,您现在可以轻松地做到这一点:
val liveData = combineTuple(liveData1, liveData2, liveData3).map { (value1, value2, value3) ->
// do something with nullable values
}
liveData.observe(this) { mappedValue ->
// do something with mapped value
}
您的示例将如下更改
fun getSourceR(): MutableLiveData<Object_R>() {}
fun getSourceS(): MutableLiveData<Object_S>() {}
fun getSourceU(): MutableLiveData<Object_U>() {}
combineTuple(getSourceR(), getSourceS(), getSourceU()).map { (r, s, u) ->
sources ->
Log.d("MergeLiveData", r?.methodOf_R)
Log.d("MergeLiveData", s?.methodOf_S)
Log.d("MergeLiveData", u?.methodOf_U)
}
我建议您尝试一下。