首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用RxJava处理分页

使用RxJava处理分页
EN

Stack Overflow用户
提问于 2015-01-20 22:03:21
回答 3查看 16.5K关注 0票数 32

我在一个安卓应用程序上使用Retrofit + RxJava,并问自己如何处理应用程序接口分页来链接调用,直到检索到所有数据。是这样的:

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

ApiResponse对象有一个简单的结构:

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

该接口将返回一个下一页的值,直到最后一页。

有什么好方法可以做到这一点吗?尝试组合一些flatMaps(),但没有成功。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-23 14:29:23

您可以递归地对其进行建模:

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

      });
}

然后,为了消耗它,

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

这应该会得到一个按顺序到达的ResponseObject流,并且很可能是以页面大小的块到达的。

票数 65
EN

Stack Overflow用户

发布于 2016-07-21 19:34:38

Iopar给出了一个很好的例子。

只是一个小小的补充。

如果您想在一个onNext()调用中获取所有页面。

当你想用更多的观察值来压缩这个结果时,它会很有帮助。

你应该这样写:

private List<String> list = new LinkedList() {
    {
        add("a");
        add("b");
        add("c");
    }
};

int count = 1;

public Observable<List<String>> getAllStrings(int c) {
    return Observable.just(list)
            .concatMap(
                    strings -> {
                        if (c == 3) {
                            return Observable.just(list);
                        } else {
                            count += 1;
                            return Observable.zip(
                                    Observable.just(list),
                                    getAllStrings(count),
                                    (strings1, strings2) -> {
                                        strings1.addAll(strings2);
                                        return strings1;
                                    }
                            );
                        }
                    }
            );
}

使用

getAllStrings(0)
        .subscribe(strings -> {
            Log.w(TAG, "call: " + strings);
        });

你将会得到:

call: [a, b, c, a, b, c, a, b, c, a, b, c]
票数 3
EN

Stack Overflow用户

发布于 2015-12-20 13:30:49

我在一个类似的帖子中回答了我的解决方案:https://stackoverflow.com/a/34378263/143733

@Iopar提供的解决方案的诀窍或修改是包含一个可以通过各种方式发出的“触发器”可观察物。

在我发布的代码中,一旦处理了一整页的元素,它就会发出,但是它也可以基于用户单击按钮/滚动而发生。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28047272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档