我正在考虑将我的android应用程序转换为使用Rxjava来处理网络请求。我目前访问的webservice服务类似于:
getUsersByKeyword(String query, int limit, int offset)
据我所知,观察体是一个“推”而不是“拉”的界面。所以我是这样理解事情的:
这就是我的问题所在。以前我只会向webservice询问我到底想要什么,再次使用偏移量进行查询。但在这种情况下,这将涉及到创建另一个可观察对象并订阅它,这有点违背了要点。
我应该如何处理我的应用程序中的分页?(这是一个android应用程序,但我不认为这是相关的)。
发布于 2015-08-11 16:41:19
这是硬摇滚!)所以我们有对网络的请求:
getUsersByKeyword(String query, int limit, int offset)
例如,此请求返回
List< Result >
如果我们使用RetroFit进行联网,该请求将如下所示:
Observable< List< Result >> getUsersByKeyword(String query, int limit, int offset)
因此,我们希望从服务器获取所有Result
。
所以它看起来就像这样
int page = 50;
int limit = page;
Observable
.range(0, Integer.MAX_VALUE - 1)
.concatMap(new Func1<Integer, Observable<List<Result>>>() {
@Override
public Observable<List<Result>> call(Integer integer) {
return getUsersByKeyword(query, integer * page, limit);
}
})
.takeWhile(new Func1<List<Result>, Boolean>() {
@Override
public Boolean call(List<Result> results) {
return !results.isEmpty();
}
})
.scan(new Func2< List<Result>, List<Result>, List<Result>>() {
@Override
public List<Result> call(List<Result> results, List< Result> results2) {
List<Result> list = new ArrayList<>();
list.addAll(results);
list.addAll(results2);
return list;
}
})
.last()
.subscribe(new Subscriber<List<Result>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<Results> results) {
}
});
代码已经测试过了!
发布于 2015-01-20 11:43:08
因此,如果这是单向分页,下面是一种您可以尝试的模式。这段代码尚未运行或编译,但我已经尝试过过度注释,以便解释发生了什么。
private static final int LIMIT = 50;
// Given: Returns a stream of dummy event objects telling us when
// to grab the next page. This could be from a click or wherever.
Observable<NextPageEvent> getNextPageEvents();
// Given:
// The search query keywords. Each emission here means a new top-level
// request;
Observable<String> queries;
queries.switchMap((query) -> getNextPageEvents()
// Ignore 'next page' pokes when unable to take them.
.onBackPressureDrop()
// Seed with the first page.
.startWith(new NextPageEvent())
// Increment the page number on each request.
.scan(0, (page, event) -> page + 1)
// Request the page from the server.
.concatMap((page) -> getUsersByKeyword(query, LIMIT, LIMIT * page)
// Unroll Observable<List<User> into Observable<User>
.concatMap((userList) -> Observable.from(userList))
.retryWhen(/** Insert your favorite retry logic here. */))
// Only process new page requests sequentially.
.scheduleOn(Schedulers.trampoline())
// Trampoline schedules on the 'current thread', so we make sure that's
// a background IO thread.
.scheduleOn(Schedulers.io());
这应该会让“下一页事件”信号每次都会触发下一页数据的加载,并且在加载页面时遇到错误时不会跳转页面。如果它接收到新的搜索查询,它还会在顶级完全重新启动。如果我(或其他人?)有时间,我想检查一下我对弹床和背压的假设,并确保它阻止了在加载页面时过早获取下一个页面的任何尝试。
发布于 2014-10-13 02:42:09
我已经这样做了,实际上并不是那么难。
方法是对firstRequestsObservable中的每个第一个请求(偏移量为0)进行建模。为了简单起见,您可以将其作为PublishSubject,在其中调用onNext()
以提供下一个请求,但还有更智能的非主题方法(例如,如果在单击按钮时完成请求,则requestObservable是通过某些操作符映射的clickObservable )。
一旦您有了firstRequestsObservable
,您就可以从firstRequestsObservable
通过flatMapping执行responseObservable
,依此类推,以进行服务调用。
现在诀窍来了:创建另一个从responseObservable
映射的名为subsequentRequestsObservable
的可观察对象,增加偏移量(为此,最好在响应数据中包括原始请求的偏移量)。引入此可观察对象后,现在必须更改responseObservable
的定义,以便它也依赖于subsequentRequestsObservable
。然后,您将获得一个循环依赖,如下所示:
firstRequestsObservable -> responseObservable -> subsequentRequestsObservable -> responseObservable -> subsequentRequestsObservable -> ...
要打破这个循环,您可能希望在subsequentRequestsObservable
的定义中包含一个filter
运算符,过滤掉偏移量将超过“总”限制的情况。循环依赖还意味着您需要将其中一个作为主题,否则将无法声明可观察对象。我推荐responseObservable
作为这个主题。
因此,总而言之,您首先将responseObservable初始化为一个主题,然后声明firstRequestsObservable,然后将subsequentRequestsObservable声明为通过某些运算符传递responseObservable的结果。然后,可以通过使用onNext
来“输入”responseObservable。
https://stackoverflow.com/questions/26321023
复制相似问题