I need to concat multiple API calls and I'd like to use retrofit2 and rxJava observables to do that. My scenario is as follows:
I must do a first call that will return an array of objects, the response will be something like:
[{"title": "Title 1", "id": "1"}, {"title": "Title 2", "id": "2"}]
Then I need to do an API call per each object, so each object's API response will be something like:
[{"title": "Chapter A", "id": "1A", ...}, {"title": "Chapter B", "id": "1B", ...}, ...]
So I want to concat all those calls and merge it in a unique response object that would have all information. How could I do that? How can I do the first call then with the response do a call per object and wait till all calls have been done and merge the results?
Thanks a lot
Suppose you have objects with defined properties:
public class TvShow {
public String title;
public Long id;
public List<TvChapter> chapterList;
}
public class TvChapter {
public String title;
public String id;
}
And you already have methods to get data:
public Observable<List<TvShow>> getShows()
public Observable<List<TvChapter>> getTvChapters(Long tvShowId)
Here is the combined RxJava stream that returns Observable<List<TvShow>>
:
getShows()
.flatMap(new Func1<List<TvShow>, Observable<TvShow>>() {
@Override
public Observable<TvShow> call(List<TvShow> tvShows) {
return Observable.from(tvShows);
}
}).flatMap(new Func1<TvShow, Observable<TvShow>>() {
@Override
public Observable<TvShow> call(TvShow tvShow) {
return Observable.zip(Observable.just(tvShow),
getTvChapters(tvShow.id),
new Func2<TvShow, List<TvChapter>, TvShow>() {
@Override
public TvShow call(TvShow tvShow, List<TvChapter> tvChapters) {
tvShow.chapterList = tvChapters;
return tvShow;
}
});
}
}).toList();
The idea is to:
getShows
)Observable.from()
operator)getTvChapters(tvShow.id)
)tvChapters
call with tvShow
Observable.toList()
operator)using lambdas
getTitlesList() //first API call that returns Observable<Titles>
.flatmap(titles -> Observable.from(titles)) //forcing list to emit each element separately
.flatmap(title -> getDetail(title)) //second API call that returns Observable<Detail>
.toList() //collect all emitted items to list
.subscribeOn(Schedulers.io()) // don't forget to apply async scheduler,
// otherwise you'll get *android.os.NetworkOnMainThreadException*
.observeOn(AndroidSchedulers.mainThread()) //and switch thread back to main, if needed
.subscribe(details -> {
//process your details list
}, e -> {
//error handling
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With