Handle Paging with RxJava

Rafael Toledo picture Rafael Toledo · Jan 20, 2015 · Viewed 14.9k times · Source

I'm using Retrofit + RxJava on an Android app and am asking myself about how to handle the API pagination to chain calls until all data is being retrieved. Is something like this:

Observable<ApiResponse> getResults(@Query("page") int page);

The ApiResponse object has a simple structure:

class ApiResponse {
    int current;
    Integer next;
    List<ResponseObject> results;
}

The API will return a next value until is last page.

There's some good way to achieve this? Tried to combine some flatMaps(), but had no success.

Answer

lopar picture lopar · Jan 23, 2015

You could model it recursively:

Observable<ApiResponse> getPageAndNext(int page) {
  return getResults(page)
      .concatMap(new Func1<ApiResponse, Observable<ApiResponse>>() {

        @Override
        public Observable<ApiResponse> call(ApiResponse response) {
          // Terminal case.
          if (response.next == null) {
            return Observable.just(response);
          }
          return Observable.just(response)
              .concatWith(getPageAndNext(response.next));
        }

      });
}

Then, to consume it,

getPageAndNext(0)
    .concatMap(new Func1<ApiResponse, Observable<ResponseObject>>() {

        @Override
        public Observable<ResponseObject> call(ApiResponse response) {
          return Observable.from(response.results);
        }

    })
    .subscribe(new Action1<ResponseObject>() { /** Do something with it */ });

That should get you a stream of ResponseObject that will arrive in order, and most likely arrive in page-size chunks.