Mitkins
Mitkins

Reputation: 4351

RxJava - Combining multiple/different web service calls

I'm working with the Basecamp api to return and display to do lists. Here's a sample of what I'm doing at the moment:

bcxClient
  .fetchToDoLists()
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Action1<List<BcxToDoList>>() {
    @Override
    public void call(List<BcxToDoList> bcxToDoLists) {

      for( final BcxToDoList toDoList : bcxToDoLists ) {
        bcxClient
          .fetchToDos( toDoList.bucket.id )
          .subscribeOn( Schedulers.io() )
          .observeOn( AndroidSchedulers.mainThread() )
          .subscribe( new Action1<List<BcxToDo>>() {
            @Override
            public void call(List<BcxToDo> bcxToDos) {
              for( BcxToDo toDo : bcxToDos ) {
                toDoList.toDos.add( toDo );
              }
            }
          }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
              throwable.printStackTrace();
            }
          });
      }

      mLoremTextView.setText(bcxToDoLists.get(0).name);
    }

  }, new Action1<Throwable>() {
    @Override
    public void call(Throwable throwable) {
      throwable.printStackTrace();
    }
  });

fetchToDoLists and fetchToDos are Retrofit web service calls that return the BcxToDoList and BcxToDos Observables.

In the subscription to fetchToDoLists I loop through each BcxToDoList, call fetchToDos and attach my BcxToDo objects to the original list.

As you can see, it's a little verbose. I could just separate this into two statements to make it a little bit more readable. But, that's not very Rx. Is there a different way to do this in RxJava and improve its readability?

I could use lambdas to make this compact, but at this stage I'm more interested in what features in RxJava I could take advantage of.

Upvotes: 3

Views: 2461

Answers (1)

krp
krp

Reputation: 2247

You should not "break the chain" in your RxJava calls, hence you will need flatMap to chain them. Also Observable.from() lets you split List of elements into separate Observables. Next, you can use toList to get elements back into list. Here's an example :

bcxClient
        .fetchToDoLists()
        .flatMap(new Func1<List<BcxToDoList>, Observable<BcxToDoList>>() {
            @Override
            public Observable<BcxToDoList> call(List<BcxToDoList> bcxToDoLists) {
                return Observable.from(bcxToDoLists);
            }
        })
        .flatMap(new Func1<BcxToDoList, Observable<List<BcxToDo>>>() {
            @Override
            public Observable<List<BcxToDo>> call(BcxToDoList bcxToDoList) {
                return bcxClient
                        .fetchToDos(bcxToDoList.bucket.id);
                        .map(new Func1<List<BcxToDo>, BcxToDoList>() {
                            @Override
                            public BcxToDoList call(List<BcxToDo> bcxToDos) {
                                bcxToDoList.toDos.addAll(bcxToDos);
                                return bcxToDoList;
                            }
                        });
            }
        })
        .toList()
        .subscribe(...);

Upvotes: 1

Related Questions