Reputation: 6150
TL;DR: I want to execute multiple Call
s (Retrofit) like you can .zip()
multiple Observable
s (RxJava2).
I have a retrofit2 function:
@GET("/data/price")
Call<JsonObject> getBookTitle(@Query("id") String id, @Query("lang") String lang);
I can execute it (async) in code with enquene()
:
ApiProvider.getBooksAPI().getBookTitle(bookId, "en").enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) { }
@Override
public void onFailure(Call<JsonObject> call, Throwable t) { }
});
Now I want to execute multiple Call
s at once (get multiple book titles) and be notified when all requests are done. Here is when I am missing knowledge.
I know I could start using Observable
(RXJava2) instead of Call
(Retrofit2):
@GET("/data/price")
Observable<JsonObject> getBookTitle(@Query("id") String id, @Query("lang") String lang);
and then merge calls like in below example. But this code seems much more complex and long (especially if I only need 1 book title). Isn't there any way I could merge Call
s without using Observable
?
List<Observable<JsonObject>> mergedCalls = new ArrayList<>();
mergedCalls.add(ApiProvider.getBooksAPI().getBookTitle(bookId1, "en"));
mergedCalls.add(ApiProvider.getBooksAPI().getBookTitle(bookId2, "en"));
mergedCalls.add(ApiProvider.getBooksAPI().getBookTitle(bookId3, "en"));
Observable<List<JsonObject>> observable = Observable.zip(calls, responses -> {
// merge responses, return List
...
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
observer = new DisposableObserver<List<JsonObject>> () {
@Override
public void onNext(List<JsonObject> result) { // got all API results }
@Override
public void onError(Throwable e) { }
@Override
public void onComplete() { }
};
observable.subscribe(observer);
Upvotes: 6
Views: 1068
Reputation: 31438
Using RxJava
is the easy way of merging Retrofit Calls
. Merging Calls
manually by enqueuing
all Calls
and doing something when all of them invoke onResponse
, will probably be more complex than simply using Observable.zip(...)
.
The other choice that you have is using Kotlin coroutines (now Retrofit has out of the box support for them). But that depends on the Kotlin presence in your code and your willingness of using coroutines.
EDIT: (Answering your question from the comment)
If you really think about Calls
and RxJava
Observables
you don't really have to do anything more when using RxJava
. When using raw Calls
you still have to:
Views
(observeOn(AndroidSchedulers.mainThread())
)subscribeOn(Schedulers.io())
)Activity
/Fragment
/Something else
is no longer present (disposing of the Disposable
in RxJava
handles that)You can significantly simplify your example:
Observable
& Observer
. Simply use the subscribe
method which returns Disposable
. And then maintain just this one Disposable
.onComplete
so you can use the simpler version of .subscribe(...)
.subscribeOn(Schedulers.io())
by properly creating your RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io())
when building the Retrofit
instance.BooksApi booksApi = ApiProvider.getBooksAPI();
List<Observable<JsonObject>> mergedCalls = new ArrayList<>();
mergedCalls.add(booksApi.getBookTitle(bookId1, "en"));
mergedCalls.add(booksApi.getBookTitle(bookId2, "en"));
mergedCalls.add(booksApi.getBookTitle(bookId3, "en"));
final Disposable disposable = Observable
.zip(mergedCalls, responses -> {
// merge responses, return List
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(list -> {
// got all API results
}, throwable -> {
});
Doing that for one call would be as simple as:
final Disposable disposable = booksApi
.getBookTitle(bookId1, "en")
.observeOn(AndroidSchedulers.mainThread())
.subscribe(title -> {
// got the result
}, throwable -> {
});
Upvotes: 2