2017-08-28 4 views
1

WebサービスAPIは、ページングを使用することがあります。ここで、Webサービス呼び出しのパラメータは、取得するページを示します。これらは、大きく2種類に分けることができます:パラメータがページを要求するページ単位のWebサービス呼び出しにRxJavaを使用する方法、各ページが前のページのレスポンスに依存する、再帰を使用しない場合

  • ものは任意のページ応答とは無関係である

    (例えば、「10のページサイズで、私のページ#3を与えます」)ページを要求するためのパラメータがいくつか前のページ応答(例えば、「fooの識別子を持つ項目の後に私の次の10の項目を与える)に依存している
  • ワンズ

This SO answer最初のシナリオをカバーうまく、どこにWebサービスはページ番号だけを必要としており、与えられたページの応答から判断する必要があるのは、完了したかどうかである。

This SO answerは再帰に依存しているため、大きなデータセットの場合はStackOverflowErrorで死にます。

Relay's specification for paginationは、前の応答から "カーソル"を与えて、そのカーソルの後の次の項目を取得する必要があるため、リレー対応のGraphQLを使用したWebサービス(GitHubのAPIなど)では、ポジション。だから、私はこのための非再帰的なアプローチを見つけようとしています。それでも、すべてのものを単一のマスターObservableにまとめています。 WebサービスAPIをブロックしているか、そしてソリューションをブロックして喜んでいる場合

+0

:あなたは次のような出力が表示されます。このテストを実行

'Flowable.observeOn(Schedulers.io())' - 内部 'Flowable'コールの内部 –

+0

WebサービスAPIがブロックされているか、またはObservableを返しますか?問題は、APIを使用するには、次の結果を要求するために前の結果が完了するのを待つ必要があるということです。あなたがブロックしようとするならば、解決は簡単です。 – hgrey

答えて

2

は、再帰的な答えから表記を使用して

Observable.generate(() -> new ApiResponse(page), (s, emitter) -> { 
    ApiResponse r = getResults(s.next);    
    emitter.onNext(r); 
    if (r.next == null) emitter.onComplete(); 
    return r; 
}); 

簡単です。

ブロッキングが望ましくない場合は、私はそれが正しい取得する場合、私は知らないが、私はあなたがその問題を解決するためにRxJavaにSyncOnSubscribe.createStatefulを使用することができることを信じているので

Flowable 
    .just(new ApiResponse(page)) 
    .compose(FlowableTransformers.expand(r -> r.next == null ? Flowable.empty() : getResults(r.next))); 
+0

これは興味深い点です。私は既存のObservableベースのAPIを使用していましたが、ブロッキングコールを使用して説明したようにラップすることができます。私はそれを試してみましょう - 多くの感謝! – CommonsWare

+0

ブロックされていないが追加のライブラリが必要な更新された回答の2番目の部分を参照してください – hgrey

0

ようRxJava2ExtensionsからFlowableTransformers.expandを使用することができます。

私のサンプルをチェックアウト:

class SimpleTest { 
    @Test 
    fun testRequestTenPages() { 
    getPaginatedDataFromApi() 
     .take(10) 
     .subscribe { println(it) } 
    } 

    fun apiCall(previous: Response? = null) : Response { 
    return previous?.let { 
     val newPage = it.page + 1 
     previous.copy(id = "${it.id}_$newPage", page = newPage) 
    } ?: Response("1", 1) 
    }  

    fun getPaginatedDataFromApi(): Observable<Response> { 
    val syncOnSubscribe = SyncOnSubscribe.createStateful<Response?, Response>(
     { null }, 
     { previous, observer -> 
      val response = apiCall(previous) 
      observer.onNext(response) 
      [email protected] response 
     } 
    ) 

    return Observable.create(syncOnSubscribe) 
    } 

    data class Response(val id: String, val page: Int) 
} 

私は国家としての最後の応答を保持AN次の応答を生成するためにそれを使用した観測可能ステートフルを作成しています。例えば ​​- あなたはまだいくつかの非同期境界演算子で増補「再帰的な」解決策を、使用することができます

Response(id=1, page=1) 
Response(id=1_2, page=2) 
Response(id=1_2_3, page=3) 
Response(id=1_2_3_4, page=4) 
Response(id=1_2_3_4_5, page=5) 
Response(id=1_2_3_4_5_6, page=6) 
Response(id=1_2_3_4_5_6_7, page=7) 
Response(id=1_2_3_4_5_6_7_8, page=8) 
Response(id=1_2_3_4_5_6_7_8_9, page=9) 
Response(id=1_2_3_4_5_6_7_8_9_10, page=10) 
+0

これはObservable.generateと同等です。 – hgrey

関連する問題