別のアプローチは、トークンストリームを使用することです:トークンが空になるまで結果が
public Observable<Window> paging() {
Subject<Token, Token> tokenStream = BehaviorSubject.<Token>create().toSerialized();
tokenStream.onNext(Token.startToken());
Observable<Window> dataStream =
Observable.defer(() -> tokenStream.first().flatMap(this::remoteData))
.doOnNext(window -> tokenStream.onNext(window.getToken()))
.repeatWhen(completed -> completed.flatMap(__ -> tokenStream).takeWhile(Token::hasMore));
return dataStream;
}
で一度新鮮なリモートデータが得られ、ストリーム、および再サブスクライブするために、最初のトークンのためのデータを取得し、次のトークンをプッシュ
Window{next token=Token{key='1'}, data='data for token: Token{key=''}'}
Window{next token=Token{key='2'}, data='data for token: Token{key='1'}'}
Window{next token=Token{key='3'}, data='data for token: Token{key='2'}'}
Window{next token=Token{key='4'}, data='data for token: Token{key='3'}'}
Window{next token=Token{key='5'}, data='data for token: Token{key='4'}'}
Window{next token=Token{key='6'}, data='data for token: Token{key='5'}'}
Window{next token=Token{key='7'}, data='data for token: Token{key='6'}'}
Window{next token=Token{key='8'}, data='data for token: Token{key='7'}'}
Window{next token=Token{key='9'}, data='data for token: Token{key='8'}'}
Window{next token=Token{key='10'}, data='data for token: Token{key='9'}'}
ジャストアイデア、なぜwouldntのコピーpastableサンプル
public class RxPaging {
public Observable<Window> paging() {
Subject<Token, Token> tokenStream = BehaviorSubject.<Token>create().toSerialized();
tokenStream.onNext(Token.startToken());
Observable<Window> dataStream =
Observable.defer(() -> tokenStream.first().flatMap(this::remoteData))
.doOnNext(window -> tokenStream.onNext(window.getToken()))
.repeatWhen(completed -> completed.flatMap(__ -> tokenStream).takeWhile(Token::hasMore));
return dataStream;
}
private Observable<Window> remoteData(Token token) {
/*limit number of pages*/
int page = page(token);
Token nextToken = page < 10
? nextPageToken(token)
: Token.endToken();
return Observable
.just(new Window(nextToken, "data for token: " + token))
.delay(100, TimeUnit.MILLISECONDS);
}
private int page(Token token) {
String key = token.getKey();
return key.isEmpty() ? 0 : Integer.parseInt(key);
}
private Token nextPageToken(Token token) {
String tokenKey = token.getKey();
return tokenKey.isEmpty() ? new Token("1") : nextToken(tokenKey);
}
private Token nextToken(String tokenKey) {
return new Token(String.valueOf(Integer.parseInt(tokenKey) + 1));
}
public static class Token {
private final String key;
private Token(String key) {
this.key = key;
}
public static Token endToken() {
return startToken();
}
public static Token startToken() {
return new Token("");
}
public String getKey() {
return key;
}
public boolean hasMore() {
return !key.isEmpty();
}
@Override
public String toString() {
return "Token{" +
"key='" + key + '\'' +
'}';
}
}
public static class Window {
private final Token token;
private final String data;
public Window(Token token, String data) {
this.token = token;
this.data = data;
}
public Token getToken() {
return token;
}
public String getData() {
return data;
}
@Override
public String toString() {
return "Window{" +
"next token=" + token +
", data='" + data + '\'' +
'}';
}
}
@Test
public void testPaging() throws Exception {
paging().toBlocking().subscribe(System.out::println);
}
}
申し訳ありませんが、私はそれがうまくいくとは思いません。結果は設定されたスキャンの最初の結果になりますが、メイン実行スレッドのフローによってcurrentKeyがまだ設定されていないことがわかり、終了します。 –
あなたが正しいように見えます。問題は鍵です。例えば、それを生成するための規則的な方法がない場合。 "1"、 "2"などとすると、ページ数が多すぎると独自の問題がある再帰的な解決策に悩まされていると思います。 – JohnWowUs
件名と副作用を使用したハックなソリューションの編集済みの回答を参照してください。 – JohnWowUs