关于SO,我在这个问题上看到了许多变化。但是,没有什么能代表我的情况。我已经进行了一些测试,但是还不清楚如何继续执行下面的方法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();
}
}
}
如果要创建一个快速的Java项目,下面是一个build.gradle
文件:
plugins {
id 'java-library'
}
repositories {
mavenCentral()
}
dependencies {
compile 'io.reactivex:rxjava:1.3.8'
testCompile 'junit:junit:4.12'
}
谢谢。
答案 0 :(得分:1)
PageProvider
的实现不正确(您的页面未链接),但是一旦修复,您可以使用来实现分页
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;
}
答案 1 :(得分:1)
一种可能的解决方案是类似的东西?
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))
;
}
不确定这是最好的解决方案,但希望对您有所帮助。
答案 2 :(得分:1)
抱歉,我错过了RxJava 1.x没有操作符repeatUntil()
。但这可以通过将repeat()
与takeUntil()
组合来解决。
在这里:
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))
;
答案 3 :(得分:0)
我认为最简单的方法是让您的PageProvider实现Iterable
并返回按顺序遍历页面的Iterator<Page>
。有了这些后,就可以简单地进行Observable.from(pageProvider)
。这样做的好处是,如果您愿意,也可以使用Java的本机forEach
。
或者,您可以使用Observable.create
,并使用onNext
并最终调用onComplete
将项目逐项放入其中。
最后,如果您不关心订单,或者将Map
更改为订购的商品,则只需执行Observable.from(map.values())
。
答案 4 :(得分:0)
NB:虽然这是一个答案,但我不认为这是最好的。
这是我解决的方式(所有代码,包括一项新测试,以确保PageProvider
正常运行)。这类似于@ctranxuan的答案。我绝对愿意提出改进建议。我不喜欢的部分是使用AtomicReference
get()
和set(..)
可能会对性能产生影响。
import org.junit.Test;
import rx.Observable;
import rx.Single;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class RxJava1TakeUntilTest {
@Test
public void testCountNumberOfPages() {
int count = 3;
PageProvider provider = new PageProvider(count);
AtomicReference<PageProvider.Page> holder = new AtomicReference<>(null);
Observable.just(holder) // reference to holder of current page
.repeat() // repeat forever
.flatMapSingle( // get a page
it -> {
PageProvider.Page page = it.get();
return provider.getPage(page == null ? null : page.next);
})
.map( // update holder to latest response
page -> {
holder.set(page);
return page;
})
.takeUntil(page -> page.done())
.reduce(0, (total, page) -> total + 1)
.test()
.assertResult(count);
}
@Test
public void testPageProvider() {
PageProvider provider = new PageProvider(2);
provider
.getPage(null)
.map(
page -> {
assertNotNull(page);
assertNotNull(page.current);
assertNotNull(page.next);
return page.next;
})
.flatMap(provider::getPage)
.map(
page -> {
assertNotNull(page);
assertNotNull(page.current);
assertNull(page.next);
return page;
})
.test()
.assertNoErrors();
}
public static class PageProvider {
int pageCount;
Page firstPage;
Map<String, Page> pages = new HashMap<>();
public PageProvider(int pageCount) {
this.pageCount = pageCount;
String next = uuid();
for (int i = 0; i < pageCount; i++) {
Page page = new Page(next, i == pageCount - 1 ? null : uuid());
if (i == 0) firstPage = page;
pages.put(page.current, page);
next = page.next;
}
}
public Single<Page> getPage(String index) {
return Single.just(index == null ? firstPage : pages.get(index));
}
static String uuid() {
return UUID.randomUUID().toString();
}
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;
}
}
}
}
答案 5 :(得分:0)
另一种可能的解决方案是使用echo '<option value="'. htmlspecialchars($username) .'">'. htmlspecialchars("$type $username $Lastname") .'</option>';
:
Observable.create()
...在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);
}
}
中做了些微更改。
但是在这种情况下,您正在创建一些PageProvider
(与页面数一样多)。