doOnNext

时间:2018-03-26 22:09:08

标签: android rx-java

我的应用程序中有许多用于网络请求的Observable。由于这么多是相同的,我对它们应用了一个Observable转换:

/**
 * Creates a transformer that applies the schedulers and error handling for all of the observables in this ViewModel.
 */
private fun applyTransformations(): Observable.Transformer<NetworkState, NetworkState> {
    return Observable.Transformer { observable ->
        observable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn { NetworkState.Error(it) }
                .doOnNext { publishState(it) }
                .startWith(NetworkState.Loading())
    }
}

我试图通过上述目标实现的目标:

  • 应用一致的计划程序
  • 通过返回我的密封类的实例来处理任何错误。
  • 通过发布observable返回的状态来处理任何onNext。
  • 通过发送加载状态开始。

这项工作大部分都很好,但我注意到的是,当我调用startWith和加载状态时,doOnNext()实际上从未处理过它。换句话说,永远不会为我的加载状态调用publishState()

在我设置可观察量的地方,我不想添加订阅者,因为上面的doOnNext()就是我所需要的:

val subscription = repository.getInstagramPhotos(count)
        .map { mapIGPhotoResponse(it) }
        .compose(applyTransformations())
        .subscribe()

但是,如果我要提供上面的订户,它将处理加载状态。它还将处理两个onNext()个调用 - 一个用于提供的订阅者,另一个用于转换中的doOnNext

有没有办法修改此startWith来自我doOnNext指定的任何内容的发票?我使用的是RxJava 1。

编辑:只是为了澄清一些,如果我追踪发射的东西,我希望看到两件事。 Loading -> Success。我实际看到的只是Success。如果我向观察者提供订阅者,我会看到Loading -> Success -> Success

1 个答案:

答案 0 :(得分:5)

startWith应该在doOnNext之前。

Rxjava方法虽然看起来像是使用了构建器模式,但实际上并不是这样。每次应用运算符时,它们都会返回一个新的observable。在您的情况下,您的doOnNext observable在您开始之前就已完成observable,因此不会使用您在startWith中提供的内容调用它的消费者。

理想情况下,你应该选择:

observable
                .startWith(NetworkState.Loading()) 
                .doOnNext { publishState(it) }
                .onErrorReturn { NetworkState.Error(it) }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())

另外,如果发生这种情况,请小心订阅没有消费者onEror。由于没有任何东西可以使用onError,因此RxJava会使您的应用程序崩溃,因为它没有任何通知错误。考虑在订阅中将doOnNext替换为成功消费者,如果要忽略它,请考虑替换错误的消费者。

同样doOnNext通常用于副作用,例如记录和排序,它们比真正的功能操作符更方便。