Is there any possible way of using livedata to run multiple async calls in parallel??
Let say I have 4 async calls. I want to wait until everything is done and later use the result from all the 4 calls accordingly.
One way I can think of is this
public class MakeParallel {
private final CountDownLatch countDown = new CountDownLatch(4);
public void firstCall() {
Transformation.map(makeFirstCall(), input -> {
if(input.isSuccessful()) {
countDownLatch.countDown();
checkResult();
}
return input;
}
}
public void secondCall() {
Transformation.map(makeSecondCall(), input -> {
if(input.isSuccessful()) {
countDownLatch.countDown();
checkResult();
}
return input;
}
}
void checkResult() {
if(countDownLatch.getCount == 0) {
// Result is ready
} else {
// Something has error
}
}
}
Is there any better way to resolve this scenario??
So the trick is to use MediatorLiveData and have it observe each LiveData object and zip the changes into a collection of some sort.
public static LiveData<ArrayList<Object>> zipLiveData(LiveData<Object>... liveItems){
final ArrayList<Object> zippedObjects = new ArrayList<>();
final MediatorLiveData<ArrayList<Object>> mediator = new MediatorLiveData<>();
for(LiveData<Object> item: liveItems){
mediator.addSource(item, new Observer<Object>() {
@Override
public void onChanged(@Nullable Object o) {
if(!zippedObjects.contains(o)){
zippedObjects.add(o);
}
mediator.setValue(zippedObjects);
}
});
}
return mediator;
}
Or in Kotlin:
fun zipLiveData(vararg liveItems: LiveData<*>): LiveData<ArrayList<Any>> {
return MediatorLiveData<ArrayList<Any>>().apply {
val zippedObjects = ArrayList<Any>()
liveItems.forEach {
addSource(it, { item ->
if (! zippedObjects.contains(item as Any)) {
zippedObjects.add(item)
}
value = zippedObjects
})
}
}}
This solution has no type safety. Feel free to customize to your needs!