nightfixed
nightfixed

Reputation: 841

RxJava for-loop with async methoods?

I am learning to use RxJava with Android. In my project, I have a single situation where I get a List of items from the server, and I need to get the details of each item, before returning the response to the UI.

The problem is: I am not sure how to sync the API calls that are called inside the for loop. I want the end result returned to the UI only after all calls in the foor loop complete.

Any hints are highly appreciated.

Sample code:

Observable<List<Favorite>> result = ApiWrapper.getFavorites(userData)
            .flatMap(new Func1<List<Favorite>, Observable<List<Favorite>>>() {
              @Override
              public Observable<List<Favorite>> call(@NonNull final List<Favorite> response) {
                for(int i = 0; i < response.size(); i++){
                  getDetailsForFavoriteItem(response.get(i));
                }
                return Observable.just(response);              
              }
            });

private Observable<Favorite> getDetailsForFavoriteItem (Favorite item){
  return ApiWrapper.getDetails(item.getId())
        .flatMap(new Func1<FavoriteDetailsResponse, Observable<Favorite>>() {
              @Override
              public Observable<Favorite> call(@NonNull final FavoriteDetailsResponse response) {
                item.setParam1(response.getParam1());
                item.setParam2(response.getParam2);
                //so on
                return Observable.just(item)//!!!issue is here ! I want this return to be called only after all the details (in the for loop) have been called              
              }
            });
}

Upvotes: 1

Views: 2512

Answers (1)

Alexander Perfilyev
Alexander Perfilyev

Reputation: 6829

First of all, your API in getDetailsForFavoriteItem() is not called because you are not subscribing to an Observable.

Second, it would be better to flatMap your first response into one Observable<Favorite> and then flatMap it again to get a details for it. Something like this:

    Observable<List<Favorite>> result = ApiWrapper.getFavorites(userData)
            .flatMapIterable(favorites -> favorites)
            .flatMap(favorite -> getDetailsForFavoriteItem(favorite))
            .toList();

You can even make parallel calls to get your details by:

    Observable<List<Favorite>> result = getFavorites()
            .flatMapIterable(favorites -> favorites)
            .flatMap(favorite -> getDetailsForFavoriteItem(favorite)
                    .subscribeOn(Schedulers.io()), maxConcurrentCalls) // be sure to limit your maxConcurrentCalls or you might get OOM error
            .toList();

Upvotes: 7

Related Questions