“转换” switchMap的概念对我来说仍然很棘手,因此我试图将其解开。 我了解,如果我有一个用Transformations.switchMap初始化的LiveDataA,它观察到LiveDataB,则当B发生变化时,它将用新MediatorLiveDataC替换LiveDataA,该MediatorLiveDataC包含附加的旧LiveDataA观察器,以便上层观察它的类可以继续观察
因此,基本上,如果我有一个提供程序LiveDataA,它包含DB或Service等内容,则很有帮助,当它连接时,将触发switchMap并激活switchMap函数以返回LiveDataC,代码如下: / p>
观察者文件(可能是通过ViewModel的片段)
myViewModel.getLastUserLD().observe(lifeCycleOwner, Observer<User> {
...add user name to some view...
}
回购文件:
val myServiceMLD = MutableLiveData<MyService>()
var lastUserLD : LiveData<User>
init{
lastUserLD = Transforamtions.switchMap(myServiceMLD) {
//the service provides a liveData with the last user
it.getLastUserLD
}
}
fun getLastUserLD() = lastUserLD
//this occurs asynchronously, at a certain time it hooks, but we don't know when
setMyService(myService: MyService) { myServiceMLD.value = myService }
因此,即使服务可能需要一些时间才能将服务绑定发送到存储库,此代码也会在服务连接时更新UI中的用户。
如果要观察多个变量,就会发生什么事情:也许我想让选定类型和区域的最后一个用户使用,但是类型和区域也可以随时更改,因此我已经解决了这一问题,不是那么通用。
回购:
val myServiceMLD = MutableLiveData<MyService>()
val userTypeMLD = MutableLiveData<Int>()
val userRegionMLD = MutableLiveData<String>()
var lastUserLD : LiveData<User>
init{
lastUserLD = Transforamtions.multipleSwitchMap(myServiceMLD, userTypeMLD, userRegionMLD) { s, ut, ur ->
//the service provides a liveData with the last user
s.getLastUserLD(ut, ur)
}
}
fun getLastUserLD() = lastUserLD
//this occurs asynchronously, at a certain time it hooks, but we don't
know when
setMyService(myService: MyService) { myServiceMLD.value = myService }
setUserType(type: Int) { userTypeMLD.value = type }
setUserRegion(region: String) { userRegionMLD.value = region }
定制的switchMap:
@MainThread
fun <W, X, Y, Z> multipleSwitchMap(source1: LiveData<W>, source2: LiveData<X>, source3: LiveData<Y>,
switchMapFunction: (W, X, Y) -> LiveData<Z>): LiveData<Z> {
return MediatorLiveData<Z>().apply {
addSource(source1, object : Observer<W> {
var mSource: LiveData<Z>? = null
override fun onChanged(w: W) {
source2.value?.let { x ->
source3.value?.let { y ->
switchMapFunction.invoke(w, x, y).let { newLiveData ->
if (mSource === newLiveData) return
mSource?.let { removeSource(it) }
mSource = newLiveData
mSource?.let { addSource(it) { z -> value = z } }
}
}
}
}
})
addSource(source2, object : Observer<X> {
var mSource: LiveData<Z>? = null
override fun onChanged(x: X) {
source1.value?.let { w ->
source3.value?.let { y ->
switchMapFunction.invoke(w, x, y).let { newLiveData ->
if (mSource === newLiveData) return
mSource?.let { removeSource(it) }
mSource = newLiveData
mSource?.let { addSource(it) { z -> value = z } }
}
}
}
}
})
addSource(source3, object : Observer<Y> {
var mSource: LiveData<Z>? = null
override fun onChanged(y: Y) {
source1.value?.let { w ->
source2.value?.let { x ->
switchMapFunction.invoke(w, x, y).let { newLiveData ->
if (mSource === newLiveData) return
mSource?.let { removeSource(it) }
mSource = newLiveData
mSource?.let { addSource(it) { z -> value = z } }
}
}
}
}
})
}
}
这行得通,但是正如我提到的,我相信并不是那么通用。 所以问题是如何使它通用,以便可以在任何数量的来源中使用它?
我已经尝试过这样做,但是,我不完全了解泛型的工作原理,或者在这种情况下是否有可能做完全泛型的事情。这是我的第一次尝试。我陷入尝试在回购中添加switchMap功能来确定其如何解析泛型类型的问题。
@MainThread
fun <Any, Z> multipleSwitchMapGeneric(switchMapFunction: (Array<out LiveData<Any>>) -> LiveData<Z>,
vararg sources: LiveData<Any>): LiveData<Z> {
return MediatorLiveData<Z>().apply {
for(source in sources) {
addSource(source, object : Observer<Any> {
var mSource: LiveData<Z>? = null
override fun onChanged(w: Any) {
switchMapFunction.invoke(sources).let { newLiveData ->
if (mSource === newLiveData) return
mSource?.let { removeSource(it) }
mSource = newLiveData
mSource?.let { addSource(it) { y -> value = y; } }
}
}
})
}
}
}
您能告诉我是否可能?如果可以,怎么办?如果不能,为什么?以及如何在回购转换中使用它?
Update1: 找到了使用3个设定值的更好方法
class TripleTrigger <X,Y,Z>(source: Triple<LiveData<X>, LiveData<Y>, LiveData<Z>>) :
MediatorLiveData<Triple<X,Y,Z>>() {
init {
addSource(source.first) {
source.second.value?.let { y -> source.third.value?.let { z -> value = Triple(it, y, z) } }
}
addSource(source.second) {
source.first.value?.let { x -> source.third.value?.let { z -> value = Triple(x, it, z) } }
}
addSource(source.third) {
source.first.value?.let { x -> source.second.value?.let { y -> value = Triple(x, y, it) } }
}
}
}
在回购中:
val myServiceMLD = MutableLiveData<MyService>()
val userTypeMLD = MutableLiveData<Int>()
val userRegionMLD = MutableLiveData<String>()
var lastUserLD : LiveData<User>
init{
lastUserLD = Transforamtions.switchMap(TripleTrigger(myServiceMLD, userTypeMLD, userRegionMLD)) {
//the service provides a liveData with the last user
it.first.getLastUserLD(it.second, it.third)
}
}
fun getLastUserLD() = lastUserLD
//this occurs asynchronously, at a certain time it hooks, but we don't
know when
setMyService(myService: MyService) { myServiceMLD.value = myService }
setUserType(type: Int) { userTypeMLD.value = type }
setUserRegion(region: String) { userRegionMLD.value = region }
对于N个触发器仍然存在问题