Given the following setup:
I have 2 repositories: Repository A and Repository B both of them return live data.
I have a ViewModel that uses both of these repositories.
I want to extract something from Repository A and depending on the result I want to grab something from Repository B and then transform the result before returning to UI.
For this I have been looking at the LiveData Transformation classes. The examples show a single transformation of the result however I want something along the lines of chaining two transformations. How can I accomplish this?
I have tried setting something up like this but get a type mismatch on the second transformation block:
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()
})
}
})
(Also please let me know if there is an alternate/recommended approach for grabbing something for chaining these call i.e. grab something from A and then grab something from B depending on result of A and so on)
Your lambda sometimes returns the String
"stringA"
, and sometimes returns the LiveData<String>
given by:
Transformations.map(repositoryB.getData(), {
result -> result.toString()
})
This means that your lambda doesn't make sense - it returns different things in different branches.
As others have mentioned, you could write your own MediatorLiveData
instead of using the one given by Transformations
. However, I think it's easier to do the following:
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()
})
}
})
All I've done is made the first code branch also return a LiveData<String>
, so now your lambda makes sense - it's a (String) -> LiveData<String>
. I had to make one other change: use switchMap
instead of map
. This is because map
takes a lambda (X) -> Y
, but switchMap
takes a lambda (X) -> LiveData<Y>
.