使用RxJava处理分页

Raf*_*edo 26 pagination android rx-java retrofit

我在Android应用程序上使用Retrofit + RxJava,并且问自己如何处理链接调用的API分页,直到检索到所有数据.是这样的:

Observable<ApiResponse> getResults(@Query("page") int page);
Run Code Online (Sandbox Code Playgroud)

所述ApiResponse对象具有简单的结构:

class ApiResponse {
    int current;
    Integer next;
    List<ResponseObject> results;
}
Run Code Online (Sandbox Code Playgroud)

API将返回下一个值,直到最后一页为止.

有一些很好的方法来实现这一目标吗?试图结合一些flatMaps(),但没有成功.

lop*_*par 56

你可以递归地建模它:

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));
        }

      });
}
Run Code Online (Sandbox Code Playgroud)

那么,要消耗它,

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 */ });
Run Code Online (Sandbox Code Playgroud)

这应该会让你的流ResponseObject按顺序到达,并且很可能以页面大小的形式到达.

  • 每天我都会发现一个新的RxJava运算符(concatMap对我来说是新的).经过测试和批准:) (5认同)
  • 请注意,我在另一个答案中对此进行了一些改进:http://stackoverflow.com/a/29594194/1424355,用于处理递归可能会破坏堆栈的情况.此外,它可能只是一个更简单的替代方案. (3认同)
  • “递归可能会破坏堆栈”,它就崩溃了。@lopar我真的很欣赏你的解决方案,但是你能否添加该解决方案导致严重内存泄漏的信息?如果您添加另一个答案的链接,那就太好了,因为我一开始就没有注意到您的最后一条评论。 (2认同)