【发布时间】:2018-09-22 01:34:01
【问题描述】:
我有一个按页面返回项目列表的 API 调用。我用retrofit来实现,接口是:
Observable<QueryResult> queryData(@Body QueryParams params);
QueryParams 和 QueryResult 定义为:
class QueryParams {
int pageIndex, pageSize; // for pagination;
... // other query criteria
}
class QueryResult {
int pageIndex, pageSize;
int totalCount; // This is the total data size which is used to know if there are still data to retreat.
... // List of data returned by page;
}
我使用这段代码来获取 100 个数据项的第一页:
params.pageIndex = 1;
params.pageSize = 100;
queryData(params).subscribe(...);
API 旨在逐页获取数据列表,以便我可以有效地响应 UI 表示。
不知何故,在某些情况下,我需要一次获取所有数据并处理一些任务,然后再呈现给 UI。使用这样设计的界面,我必须多次调用 queryData() 直到获取所有数据或至少两次(第一次获取 totalCount 并将其传递给 pageSize 以进行第二次调用)。
那么,我的问题是如何使用 RxJava 方式链接 API 调用来获取所有数据?
提前致谢。
更新来自@Abu 的解决方案
Observable<QueryResult> query(final QueryParams params) {
return queryData(params)
.concatMap(new Func1<QueryResult, Observable<QueryResult>>() {
@Override
public Observable<QueryResult> call(final QueryResult result) {
int retrievedCount = result.getPageSize() * (result.getPageIndex() - 1) + result.resultList.size();
if (retrievedCount >= result.getCount()) {
return Observable.just(result);
}
QueryParams nextParams = params.clone();
nextParams.setPageIndex(results.getPageIndex() + 1);
return query(nextParams).map(new Func1<QueryResult, QueryResult>() {
@Override
public QueryResult call(QueryResult nextResult) {
nextResult.resultList.addAll(result.resultList);
return nextResult;
}
});
}
}
【问题讨论】:
-
我个人认为,这应该由服务器完成。您无需进行调用链,而是通过服务器执行某些机制,以便它返回所有数据而不是块。例如传递 pagesize -1 来获取所有数据。
-
看看RxJava
Zipoperator -
@Wizard 是的,我完全同意你的看法。就是在现实世界中,一些我无法触及的东西,比如隐藏在服务器后面的秘密。仍然感谢您的建议,我会尝试从服务器端寻求帮助。
-
@JohnO'Reilly 我检查了 Zip 的使用。似乎可以等待两个操作结果,一次发出。假设这两个操作不相关,可以并行执行。但就我而言,我必须至少调用一次 API 以获取总数,然后再进一步。
-
@Pai-HsiangHuang 也许你可以先使用
flatMap之类的东西
标签: android rx-java retrofit retrofit2 reactivex