I need to do:
If you don't want to do something specific with the combined results, then merge() is enough:
Observable<RegionalNews> regionalNews = ...;
Observable<NationalNews> nationalNews = ...;
Observable
.merge(regionalNews, nationalNews)
.ignoreElements()
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete(() -> { /* show alert */ })
.subscribe()
You can use zip operator to call 2 requests async and save or process their data on response.
For example.
Below are two Observable
Observable<ResponseOne> responseOneObservable = getRetrofitClient().getDataOne()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
Observable<ResponseTwo> responseTwoObservable = getRetrofitClient().getDataTwo()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
Using zip operator on above two Observable as below.
Observable<ArrayList<TestData>> testDataObservable = Observable.zip(responseOneObservable, responseTwoObservable, new Func2<ResponseOne, ResponseTwo, ArrayList<TestData>>() {
@Override
public ArrayList<TestData> call(ResponseOne responseOne, ResponseTwo responseTwo) {
ArrayList<TestData> testDataList = new ArrayList();
// process data from response responseOne & responseTwo
return testDataList;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<ArrayList<TestData>>() {
@Override
public void onNext(ArrayList<TestData> testDataList) {
}
@Override
public void onCompleted() {
Log.d(TAG, "onCompleted" );
// you can show alert here or do something when completed
}
@Override
public void onError(Throwable t) {
Log.d(TAG, "onError Throwable: " + t.toString() );
}
});
zip is the way to combine observables. Combining their results is just a consequence.
If you want to wait for both observables to finish (complete), the easiest way is to use zip. You just don't have to use the results of your requests in the combining function. Just use this function as a way to emit something different when both of those calls finish. When this function emits an item:
[...] do something when all requests completed (show alert for example)
For example like this (executing someOtherCall when both of those requests finish):
Observable<Integer> obs1 = ...;
Observable<Long> obs2 = ...;
Observable.zip(obs1, obs2, new Func2<Integer, Long, String>() {
@Override
public String call(Integer integer, Long aLong) {
return "something completely different";
}
}).flatMap(new Func1<String, Observable<Float>>() {
@Override
public Observable<Float> call(String s) {
return performSomeOtherCall();
}
}).subscribe(...);
Well it depends, as always. Do you need to process the returned values down the chain, or just save it?
In this implementation I use Single and Completable. You subscribe to the completable and you will get notified when both Singles finished.
@Test
public void name() throws Exception {
TestScheduler testScheduler = new TestScheduler();
Single<Long> request1 = Single.timer(1000, TimeUnit.MILLISECONDS, testScheduler)
.doOnSuccess(aLong -> {
System.out.println("save to db.");
});
Single<Long> request2 = Single.timer(500, TimeUnit.MILLISECONDS, testScheduler)
.doOnSuccess(aLong -> {
System.out.println("save to db.");
});
Completable completable = Single.zip(request1, request2, (aLong, aLong2) -> aLong).toCompletable();
TestObserver<Void> test = completable.test();
testScheduler.advanceTimeBy(1010, TimeUnit.MILLISECONDS);
test.assertComplete();
}
You also can use flatMapCompletable instead of doOnSuccess
@Test
public void name() throws Exception {
TestScheduler testScheduler = new TestScheduler();
Completable request1 = Single.timer(1000, TimeUnit.MILLISECONDS, testScheduler)
.flatMapCompletable(this::saveToDb);
Completable request2 = Single.timer(500, TimeUnit.MILLISECONDS, testScheduler)
.flatMapCompletable(this::saveToDb);
// need to cheat here, becuase completeable does not provide zip
Completable completable = Single.zip(request1.toSingle(() -> 1), request1.toSingle(() -> 1), (aLong, aLong2) -> aLong)
.toCompletable();
TestObserver<Void> test = completable.test();
testScheduler.advanceTimeBy(1010, TimeUnit.MILLISECONDS);
test.assertComplete();
}
private Completable saveToDb(long value) {
return Completable.complete();
}