我的应用程序中有许多用于网络请求的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())
}
}
我试图通过上述目标实现的目标:
这项工作大部分都很好,但我注意到的是,当我调用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
。
答案 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
通常用于副作用,例如记录和排序,它们比真正的功能操作符更方便。