GV_FiQst
GV_FiQst

Reputation: 1567

RxJava2 combine multiple observables to make them return single result

How to combine multiple results emmited by observables into one result and emit it once?

I have a Retrofit service:

public interface MyService {

    @GET("url")
    Observable<UserPostsResult> getUserPosts(@Query("userId") int id);

    @GET("url")
    Observable<UserPostsResult> getUserPosts(@Query("userId") int id, @Query("page") int pageId);
}

And I have a model:

public class UserPostsResult {

   @SerializedName("posts")
   List<UserPost> mPosts;

   @SerializedName("nextPage")
   int mPageId;
}

Also I have ids List<Integer> friendsIds;

My goal is to have a method like this one:

public Observable<Feed> /*or Single<Feed>*/ getFeed(List<Integer> ids) {
    ...
}

It returns one Observable or Single that does the following:

Result class:

public class Feed {
    List<UserPost> mAllPostsForEachUser;
}

EDIT (More details):

My client specifications was that I must take from social network user posts with no logging in, no token requesting. So I must parse HTML pages. That's why I have this complex structure.

EDIT (Partial solution)

public Single<List<Post>> getFeed(List<User> users) {
    return Observable.fromIterable(users)
            .flatMap(user-> mService.getUserPosts(user.getId())
                    .flatMap(Observable::fromIterable))
            .toList()
            .doOnSuccess(list -> Collections.sort(list, (o1, o2) ->
                    Long.compare(o1.getTimestamp(), o2.getTimestamp())
            ));
}

This solution doesn't include pages problem. Thats why it is only partial solution

Upvotes: 0

Views: 2464

Answers (2)

Felipe Pereira Garcia
Felipe Pereira Garcia

Reputation: 94

If you need join two response in one you should use Single.zip

Single.zip(firsSingle.execute(inputParams), secondSingle.execute(inputPrams),
            BiFunction<FirstResponse, SecondResponse, ResponseEmitted> { firstResponse, secondResponse ->
              //here you put your code
   return responseEmmitted
              }
            }).subscribe({ response -> },{ })

Upvotes: 0

Bob Dalgleish
Bob Dalgleish

Reputation: 8227

There are a number of operators which transform things into other things. fromIterable() will emit each item in the iterable, and flatMap() will convert one type of observable into another type of observable and emit those results.

Observable.fromIterable( friendsIds )
  .flatMap( id -> getUserPosts( id ) )
  .flatMap( userPostResult -> userPostResult.mPageId 
            ? getUserPosts(currentUserId, userPostResult.mPageId)
            : Observable.empty() )
  .toList()
  .subscribe( posts -> mAllPostsForEachUser = posts);

Upvotes: 1

Related Questions