I need to execute something in my view after all of the asynchronous fetches has been done , for this I have a home framgnet that fetches 3 different sections in my backend
private fun populateSectionA(){
viewModel.fetchSectionA.observe(viewLifecycleOwner, Observer {
when(it){
is Resource.Loading -> { //Handling loading }
is Resource.Success -> {
//Handles data
}
is Resource.Failure -> { //Error handling }
}
})
}
private fun populateSectionB(){
viewModel.fetchSectionB.observe(viewLifecycleOwner, Observer {
when(it){
is Resource.Loading -> { //Handling loading }
is Resource.Success -> {
//Handles data
}
is Resource.Failure -> { //Error handling }
}
})
}
private fun populateSectionC(){
viewModel.fetchSectionC.observe(viewLifecycleOwner, Observer {
when(it){
is Resource.Loading -> { //Handling loading }
is Resource.Success -> {
//Handles data
}
is Resource.Failure -> { //Error handling }
}
})
}
Here are my observers in my view, what I need to know is when all of these 3 has finished to load my UI
From my viewmodel the fetch is the same for the three sections
val fetchSectionA = liveData(viewModelScope.coroutineContext + Dispatchers.IO) {
emit(Resource.Loading())
try {
emit(repo.fetchSectionA(sectionId))
} catch (e: Exception) {
emit(Resource.Failure(e))
}
}
val fetchSectionB = liveData(viewModelScope.coroutineContext + Dispatchers.IO) {
emit(Resource.Loading())
try {
emit(repo.fetchSectionB(sectionId))
} catch (e: Exception) {
emit(Resource.Failure(e))
}
}
val fetchSectionC = liveData(viewModelScope.coroutineContext + Dispatchers.IO) {
emit(Resource.Loading())
try {
emit(repo.fetchSectionC(sectionId))
} catch (e: Exception) {
emit(Resource.Failure(e))
}
}
Now, how can I know when all of these individual fetches has been done ? I dont want to use a counter in my UI that counts to certain number untill its reached, instead I would love to give a callback to my UI when all these operations finishes
If you have the following code:
fun <T1, T2, T3> combineTuple(f1: LiveData<T1>, f2: LiveData<T2>, f3: LiveData<T3>): LiveData<Triple<T1?, T2?, T3?>> = MediatorLiveData<Triple<T1?, T2?, T3?>>().also { mediator ->
mediator.value = Triple(f1.value, f2.value, f3.value)
mediator.addSource(f1) { t1: T1? ->
val (_, t2, t3) = mediator.value!!
mediator.value = Triple(t1, t2, t3)
}
mediator.addSource(f2) { t2: T2? ->
val (t1, _, t3) = mediator.value!!
mediator.value = Triple(t1, t2, t3)
}
mediator.addSource(f3) { t3: T3? ->
val (t1, t2, _) = mediator.value!!
mediator.value = Triple(t1, t2, t3)
}
}
Then you can do:
combineTuple(fetchSectionA, fetchSectionB, fetchSectionC)
.map { (sectionA, sectionB, sectionC) ->
val sectionA = sectionA.takeIf { it != Resource.Loading } ?: return@map null
val sectionB = sectionB.takeIf { it != Resource.Loading } ?: return@map null
val sectionC = sectionC.takeIf { it != Resource.Loading } ?: return@map null
return Triple(sectionA, sectionB, sectionC)
}
If you need more or less arity combiners for LiveData, check https://github.com/Zhuinden/livedata-combinetuple-kt