给出以下设置:
我有2个存储库:存储库A 和存储库B 它们都返回实时数据。
我有一个使用这两个存储库的ViewModel。
我想从Repository A中提取一些内容,并根据结果我想从Repository B中获取一些东西,然后在返回UI之前转换结果。
为此,我一直在研究LiveData Transformation课程。这些例子显示了结果的单一转换,但是我想要链接两个转换的行。我怎么能做到这一点?
我尝试过像这样设置但在第二个转换块上出现类型不匹配:
internal val launchStatus: LiveData<String> = Transformations
.map(respositoryA.getData(), { data ->
if (data.isValid){
"stringA"
} else {
//This gives a type mismatch for the entire block
Transformations.map(repositoryB.getData(), {
result -> result.toString()
})
}
})
(另请告诉我是否有替代/推荐的方法来抓取链接这些电话的东西,即从A中抓取一些东西,然后根据A的结果从B中抓取一些东西等等)
答案 0 :(得分:5)
我用MediatorLiveData来解决这个问题。
MediatorLiveData可以观察其他LiveData
个对象并做出反应。
而不是观察任何一个存储库。我在ViewModel
类中创建了 myData (MediatorLiveData的实例)并让我的视图观察到这个对象。然后我添加Repository A作为初始源并观察它,并且如果A的结果需要它,只添加 Repository B 。这允许我保持与每个repo的实时数据相关联的转换,并且仍然以正确的顺序处理每个结果。请参阅下面的实施:
internal val myData: MediatorLiveData<String> = MediatorLiveData()
private val repoA: LiveData<String> = Transformations.map(
respositoryA.getData(), { data ->
if (data.isValid) "stringA" else ""
})
private val repoB: LiveData<String> = Transformations.map(
repositoryB.getData(), { data -> "stringB"
})
fun start() {
myData.addSource(repoA, {
if (it == "stringA") {
myData.value = it
} else {
myData.addSource(repoB, {
myData.value = it
})
}
})
}
注意:解决方案不包括可能多次添加repoB的情况,但它应该足够简单,可以处理。
答案 1 :(得分:4)
您的lambda有时返回String
"stringA"
,有时返回由以下内容提供的LiveData<String>
:
Transformations.map(repositoryB.getData(), {
result -> result.toString()
})
这意味着您的lambda没有意义-它在不同的分支中返回不同的值。
正如其他人提到的那样,您可以可以编写自己的MediatorLiveData
,而不使用Transformations
给出的密码。但是,我认为执行以下操作会更容易:
internal val launchStatus: LiveData<String> = Transformations
.switchMap(respositoryA.getData(), { data ->
if (data.isValid) {
MutableLiveData().apply { setValue("stringA") }
} else {
Transformations.map(repositoryB.getData(), {
result -> result.toString()
})
}
})
我所做的只是使第一个代码分支也返回一个LiveData<String>
,所以现在您的lambda才有意义-它是一个(String) -> LiveData<String>
。我还必须进行其他更改:使用switchMap
而不是map
。这是因为map
的值是(X) -> Y
,而switchMap
的值是(X) -> LiveData<Y>
。
答案 2 :(得分:0)
我会尝试使用switchMap而不是map:
与map()类似,将函数应用于存储在LiveData对象中的值,并将结果解包并调度到下游。传递给switchMap()的函数必须返回一个LiveData对象。
答案 3 :(得分:0)
您可以嵌套转换。
Vec<_>