web-dev-qa-db-ja.com

RxJava:オブザーバブルの連鎖

RxJavaを使用して次の連鎖のようなものを実装することは可能ですか?

loginObservable()
   .then( (someData) -> {
      // returns another Observable<T> with some long operation
      return fetchUserDataObservable(someData);

   }).then( (userData) -> {
      // it should be called when fetching user data completed (with userData of type T)
      cacheUserData(userData);

   }).then( (userData) -> {
      // it should be called after all previous operations completed
      displayUserData()

   }).doOnError( (error) -> {
      //do something
   })

このライブラリは非常に興味深いと思いましたが、お互いが以前に依存しているリクエストをチェーンする方法を理解できません。

42
Mikhail

もちろん、RxJavaは.mapこれを行います。 RxJava Wikiから:

map

基本的には、次のようになります。

loginObservable()
   .switchMap( someData -> fetchUserDataObservable(someData) )
   .map( userData -> cacheUserData(userData) )
   .subscribe(new Subscriber<YourResult>() {
        @Override
        public void onCompleted() {
           // observable stream has ended - no more logins possible
        }
        @Override
        public void onError(Throwable e) {
            // do something
        }
        @Override
        public void onNext(YourType yourType) {
            displayUserData();
        }
    });
41

これは、Googling RxJava chain observablesの場合のトップポストです。したがって、transform受け取りたくないが、それでチェーンする別の一般的なケースを追加します別のアクション(たとえば、データをデータベースに設定する)。 .flatmap()を使用します。ここに例があります

_    mDataManager.fetchQuotesFromApi(limit)
            .subscribeOn(mSchedulerProvider.io())
            .observeOn(mSchedulerProvider.ui())
            .onErrorResumeNext(Function { Observable.error<List<Quote>>(it) }) //OnErrorResumeNext and Observable.error() would propagate the error to the next level. So, whatever error occurs here, would get passed to onError() on the UI side
            .flatMap { t: List<Quote> ->
                //Chain observable as such
                mDataManager.setQuotesToDb(t).subscribe({}, { e { "setQuotesToDb() error occurred: ${it.localizedMessage}" } }, { d { "Done server set" } })
                Observable.just(t)
            }
            .subscribeBy(
                    onNext = {},
                    onError = { mvpView?.showError("No internet connection") },
                    onComplete = { d { "onComplete(): done with fetching quotes from api" } }
            )
_

これはRxKotlin2ですが、考え方はRxJavaとRxJava2でも同じです。

簡単な説明:

  • mDataManager.fetchQuotesFromApi()を使用してAPIからデータ(この例では引用符)を取得しようとします
  • オブザーバブルをサブスクライブして、.io()スレッドで処理を行い、.ui()スレッドで結果を表示します。
  • onErrorResumeNext()は、データのフェッチで発生したエラーがこのメソッドで確実にキャッチされるようにします。エラーが発生したときにチェーン全体を終了したいので、Observable.error()を返します
  • .flatmap()はチェーン部分です。 APIから取得したデータをデータベースに設定できるようにします。 .map()を使用して受信したデータを変換するのではなく、単にそのデータでsomething elseを実行していますwithoutそれを変換します。
  • 最後の一連のオブザーバブルを購読します。データの取得でエラーが発生した場合(最初に観測可能)、それはonError()で処理されます(この場合、サブスクライブされたonErrorResumeNext()に伝播されます)
  • DBオブザーバブル(flatmap()内)にサブスクライブしていることを非常に意識しています。このオブザーバブルを介して発生したエラーは、[〜#〜] not [〜#〜]最後のsubscribeBy()メソッドに伝播されません、これはsubscribe()チェーン内の.flatmap()メソッド内で処理されるためです。

コードは このプロジェクト から取得されます。このコードは https://github.com/Obaied/Sohan/blob/master/app/src/main/Java/com/obaied/にあります。 dingerquotes/ui/start/StartPresenter.kt

8
Solidak

scan()を使用してみてください

Flowable.fromArray(array).scan(...).subscribe(...)
0
lingfliu