I want to run 2 asynchronous tasks, one followed by the other (sequentially). I have read something about ZIP or Flat, but I didn't understand it very well...
My purpose is to load the data from a Local SQLite, and when it finishes, it calls the query to the server (remote).
Can someone suggests me, a way to achieve that?
This is the RxJava Observable skeleton that I am using (single task):
// RxJava Observable
Observable.OnSubscribe<Object> onSubscribe = subscriber -> {
try {
// Do the query or long task...
subscriber.onNext(object);
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
};
// RxJava Observer
Subscriber<Object> subscriber = new Subscriber<Object>() {
@Override
public void onCompleted() {
// Handle the completion
}
@Override
public void onError(Throwable e) {
// Handle the error
}
@Override
public void onNext(Object result) {
// Handle the result
}
};
Observable.create(onSubscribe)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
You can try my solutions, there are several ways to resolve your problem.
To make sure it's working, I created a stand alone working example and use this API to test: https://jsonplaceholder.typicode.com/posts/1
RestPostService.java
Solution1: Use when call multiple tasks in sequences, the result of previous tasks is always the input of the next task
Solution2: Use when call multiple tasks in sequences, all results of previous tasks is the input of the final task (for example: after uploading avatar image and cover image, call api to create new user with these image URLs):
AndroidManifest
root build.gradle
app/build.gradle
model
By the way, use Rx + Retrofit + Dagger + MVP pattern is a great combine.
The operator to do that would be
merge
, see http://reactivex.io/documentation/operators/merge.html.My approach would be to create two observables, let's say
observableLocal
andobservableRemote
, and merge the output:If you want to make sure that remote is run after local, you can use
concat
.Lukas Batteau's answer is best if the queries are not dependent on one another. However, if it is necessary for you obtain the data from the local SQLite query before you run the remote query (for example you need the data for the remote query params or headers) then you can start with the local observable and then flatmap it to combine the two observables after you obtain the data from the local query:
The flatmap function allows you to transform the local observable into a combination of the local & remote observables via the zip function. And to reiterate, the advantage here is that the two observables are sequential, and the zip function will only run after both dependent observables run.
Furthermore, the zip function will allow you to combine observables even if the underlying objects have different types. In that case, you provide a combining function as the 3rd parameter. If the underlying data is the same type, replace the zip function with a merge.