我在一个安卓应用程序上使用Retrofit + RxJava,并问自己如何处理应用程序接口分页来链接调用,直到检索到所有数据。是这样的:
Observable<ApiResponse> getResults(@Query("page") int page);
ApiResponse对象有一个简单的结构:
class ApiResponse {
int current;
Integer next;
List<ResponseObject> results;
}
该接口将返回一个下一页的值,直到最后一页。
有什么好方法可以做到这一点吗?尝试组合一些flatMaps(),但没有成功。
发布于 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
流,并且很可能是以页面大小的块到达的。
发布于 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]
发布于 2015-12-20 13:30:49
我在一个类似的帖子中回答了我的解决方案:https://stackoverflow.com/a/34378263/143733
@Iopar提供的解决方案的诀窍或修改是包含一个可以通过各种方式发出的“触发器”可观察物。
在我发布的代码中,一旦处理了一整页的元素,它就会发出,但是它也可以基于用户单击按钮/滚动而发生。
https://stackoverflow.com/questions/28047272
复制相似问题