如何使用rxjava1.x进行分页,而分页必须调用具有不同数据的每个页面?
我在这个问题上看到了很多变化。然而,没有一个能完全代表我的情况。我已经做了一个小测试,但我不清楚如何继续实现下面的方法如何使用rxjava1.x进行分页,而分页必须调用具有不同数据的每个页面?,java,rx-java,Java,Rx Java,我在这个问题上看到了很多变化。然而,没有一个能完全代表我的情况。我已经做了一个小测试,但我不清楚如何继续实现下面的方法getPages。策略是在第一次调用时调用PageProvider#getPage(null),然后调用PageProvider#getPage(page.next)(其中page是最后一次调用返回的页面),直到page.done()返回true import org.junit.Test; import rx.Observable; import rx.Single; imp
getPages
。策略是在第一次调用时调用PageProvider#getPage(null)
,然后调用PageProvider#getPage(page.next)
(其中page
是最后一次调用返回的页面),直到page.done()
返回true
import org.junit.Test;
import rx.Observable;
import rx.Single;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class RxJava1TakeUntilTest {
PageProvider provider = new PageProvider(3);
Observable<PageProvider.Page> getPages() {
// TODO: call provider.getPage(null) then provider.getPage(page.next) until page.done() is true
return null;
}
@Test
public void testTakeUntil() {
getPages().subscribe(page -> System.out.println(page.toString()));
}
public static class PageProvider {
public static class Page {
public String current;
public String next; // is null if no more pages
public Page(String current, String next) {
this.current = current;
this.next = next;
}
public boolean done() {
return next == null;
}
@Override
public String toString() {
return current + " -> " + next;
}
}
int pageCount;
Page firstPage;
Map<String, Page> pages = new HashMap<>();
public PageProvider(int pageCount) {
this.pageCount = pageCount;
for (int i = 0; i < pageCount; i++) {
Page page = new Page(uuid(), i == pageCount - 1 ? null : uuid());
if (i == 0) firstPage = page;
pages.put(page.current, page);
}
}
public Single<Page> getPage(String index) {
return Single.just(index == null ? firstPage : pages.get(index));
}
static String uuid() {
return UUID.randomUUID().toString();
}
}
}
提前感谢。我认为最简单的方法是让您的页面提供者实现
Iterable
并返回一个按顺序遍历页面的迭代器。一旦你有了它,你就可以从(pageProvider)
简单地执行Observable.from。这里的优点是,如果您愿意,还可以使用Java的原生forEach
或者,您可以使用Observable。创建并使用onNext
将您的项目逐个推入其中,最后调用onComplete
最后,如果您不关心顺序,或者您将Map
更改为一个有序的,您可以简单地执行Observable.from(Map.values())
我认为最简单的事情是让您的页面提供者实现Iterable
并返回一个按顺序遍历页面的迭代器。一旦你有了它,你就可以从(pageProvider)
简单地执行Observable.from。这里的优点是,如果您愿意,还可以使用Java的原生forEach
或者,您可以使用Observable。创建并使用onNext
将您的项目逐个推入其中,最后调用onComplete
最后,如果您不关心顺序,或者将映射
更改为有序映射,您只需执行可观察的.from(Map.values())
页面提供程序
实现不正确(您的页面未链接),但一旦修复,您可以使用
Observable<PageProvider.Page> getPages() {
BehaviorSubject<String> pageControl = BehaviorSubject.create((String)null);
Observable<PageProvider.Page> ret = pageControl.asObservable()
.concatMap(apageIndex ->
provider.getPage(apageIndex).toObservable().doOnNext(
page-> {
if (page.next == null)
pageControl.onCompleted();
else
pageControl.onNext(page.next);
}));
return ret;
}
可观察的getPages(){
BehaviorSubject pageControl=BehaviorSubject.create((字符串)null);
可观测ret=pageControl.asObservable()
.concatMap(apageIndex->
provider.getPage(apageIndex.toObservable().doOnNext(
第->{
如果(page.next==null)
pageControl.onCompleted();
其他的
pageControl.onNext(page.next);
}));
返回ret;
}
页面提供程序的实现不正确(您的页面未链接),但一旦修复,您可以使用
Observable<PageProvider.Page> getPages() {
BehaviorSubject<String> pageControl = BehaviorSubject.create((String)null);
Observable<PageProvider.Page> ret = pageControl.asObservable()
.concatMap(apageIndex ->
provider.getPage(apageIndex).toObservable().doOnNext(
page-> {
if (page.next == null)
pageControl.onCompleted();
else
pageControl.onNext(page.next);
}));
return ret;
}
可观察的getPages(){
BehaviorSubject pageControl=BehaviorSubject.create((字符串)null);
可观测ret=pageControl.asObservable()
.concatMap(apageIndex->
provider.getPage(apageIndex.toObservable().doOnNext(
第->{
如果(page.next==null)
pageControl.onCompleted();
其他的
pageControl.onNext(page.next);
}));
返回ret;
}
我也有类似的问题()
一个可能的解决方案是这样的
Flowable<Page> getPages() {
// TODO: call provider.getPage(null) then provider.getPage(page.next) until page.done() is true
AtomicReference<Page> ref = new AtomicReference<>();
return Flowable.just(ref)
.map(AtomicReference::get) // get the current page
.map(page -> page.next) // get the next index
.flatMapSingle(index -> provider.getPage(index)) // get the next page
.doOnNext(ref::set)
.repeatUntil(() -> ref.get() != null && ref.get().done())
.startWith(provider.getPage(null) // deal with 1st page
.toFlowable()
.doOnNext(ref::set))
;
}
可流动的getPages(){
//TODO:调用provider.getPage(null),然后调用provider.getPage(page.next),直到page.done()为true
AtomicReference ref=新的AtomicReference();
返回可流动。仅(参考)
.map(AtomicReference::get)//获取当前页面
.map(page->page.next)//获取下一个索引
.flatMapSingle(index->provider.getPage(index))//获取下一页
.doOnNext(参考::集)
.repeatUntil(()->ref.get()!=null&&ref.get().done())
.startWith(provider.getPage(null)//处理第一页
.toFlowable()
.doOnNext(参考::集))
;
}
不确定这是不是最好的解决方案,但我希望它能有所帮助。我也遇到过类似的问题()
一个可能的解决方案是这样的
Flowable<Page> getPages() {
// TODO: call provider.getPage(null) then provider.getPage(page.next) until page.done() is true
AtomicReference<Page> ref = new AtomicReference<>();
return Flowable.just(ref)
.map(AtomicReference::get) // get the current page
.map(page -> page.next) // get the next index
.flatMapSingle(index -> provider.getPage(index)) // get the next page
.doOnNext(ref::set)
.repeatUntil(() -> ref.get() != null && ref.get().done())
.startWith(provider.getPage(null) // deal with 1st page
.toFlowable()
.doOnNext(ref::set))
;
}
可流动的getPages(){
//TODO:调用provider.getPage(null),然后调用provider.getPage(page.next),直到page.done()为true
AtomicReference ref=新的AtomicReference();
返回可流动。仅(参考)
.map(AtomicReference::get)//获取当前页面
.map(page->page.next)//获取下一个索引
.flatMapSingle(index->provider.getPage(index))//获取下一页
.doOnNext(参考::集)
.repeatUntil(()->ref.get()!=null&&ref.get().done())
.startWith(provider.getPage(null)//处理第一页
.toFlowable()
.doOnNext(参考::集))
;
}
不确定这是不是最好的解决方案,但我希望它能有所帮助。NB:虽然这是一个答案,但我不相信这是最好的
下面是我如何解决它的(所有代码,包括一个新的测试,以确保PageProvider
正常工作)。这与@ctranxuan的答案类似。我当然愿意接受改进建议。我不喜欢的部分是使用AtomicReference
get()
&set(…)
对性能的潜在影响
import org.junit.Test;
进口接收。可观察;
进口接收单;
导入java.util.HashMap;
导入java.util.Map;
导入java.util.UUID;
导入java.util.concurrent.AtomicReference;
导入静态org.junit.Assert.as
AtomicReference<Page> ref = new AtomicReference<>();
return Observable.just(ref)
.map(AtomicReference::get) // get the current page
.map(page -> page.next) // get the next index
.flatMapSingle(index -> provider.getPage(index)) // get the next page
.doOnNext(ref::set)
.repeat()
.takeUntil(Page::done)
.startWith(provider.getPage(null) // deal with 1st page
.toObservable()
.doOnNext(ref::set))
;
Observable<Page> getPages() {
AsyncOnSubscribe<Page, Page> stateful =
AsyncOnSubscribe.createStateful(() -> provider.getPageFrom(null),
(page, requested, observer) -> {
if (!page.done()) {
observer.onNext(Observable.just(page));
}
return provider.getPageFrom(page.next);
});
return Observable.create(stateful);
}
...
public static class PageProvider {
public Page getPageFrom(String index) {
return index == null ? firstPage : pages.get(index);
}
}