我在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(),但没有成功.
我正在使用Spotify API,并希望使用RxJava链接一些分页结果.Spotify使用基于游标的分页,因此像@lopar那样的解决方案将无效.
响应来自此调用,看起来像这样(想象有50个items):
{
"artists" : {
"items" : [ {
"id" : "6liAMWkVf5LH7YR9yfFy1Y",
"name" : "Portishead",
"type" : "artist"
}],
"next" : "https://api.spotify.com/v1/me/following?type=artist&after=6liAMWkVf5LH7YR9yfFy1Y&limit=50",
"total" : 119,
"cursors" : {
"after" : "6liAMWkVf5LH7YR9yfFy1Y"
},
"limit" : 50,
"href" : "https://api.spotify.com/v1/me/following?type=artist&limit=50"
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我正在使用改造这样的前50个结果:
public class CursorPager<T> {
public String href;
public List<T> items;
public int limit;
public String next;
public Cursor cursors;
public int total;
public CursorPager() {
}
}
public class ArtistsCursorPager { …Run Code Online (Sandbox Code Playgroud) 我有一个非常标准的 API 分页问题,您可以通过一些简单的递归来处理。这是一个虚构的例子:
public Observable<List<Result>> scan() {
return scanPage(Optional.empty(), ImmutableList.of());
}
private Observable<?> scanPage(Optional<KEY> startKey, List<Result> results) {
return this.scanner.scan(startKey, LIMIT)
.flatMap(page -> {
if (!page.getLastKey().isPresent()) {
return Observable.just(results);
}
return scanPage(page.getLastKey(), ImmutableList.<Result>builder()
.addAll(results)
.addAll(page.getResults())
.build()
);
});
}
Run Code Online (Sandbox Code Playgroud)
但这显然会创建一个庞大的调用堆栈。如何强制执行此操作但维护 Observable 流?
这是一个命令式阻塞示例:
public List<Result> scan() {
Optional<String> startKey = Optional.empty();
final ImmutableList.Builder<Result> results = ImmutableList.builder();
do {
final Page page = this.scanner.scan(startKey);
startKey = page.getLastKey();
results.addAll(page.getResults());
} while (startKey.isPresent());
return results.build();
}
Run Code Online (Sandbox Code Playgroud)