【问题标题】:Observable startWith isn't emitted in doOnNext可观察的 startWith 不会在 doOnNext 中发出
【发布时间】:2018-03-26 22:09:08
【问题描述】:

我的应用中有许多用于网络请求的 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。
  • 首先发送一个 Loading 状态。

这几乎可以正常工作,但我注意到,当我调用startWith 和加载状态时,它实际上从未由doOnNext() 处理。换句话说,我的加载状态永远不会调用publishState()

在我设置 observables 的地方,我懒得添加订阅者,因为上面的 doOnNext() 就是我所需要的:

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

如果我在上面提供一个订阅者,它会处理加载状态。它还将处理两个onNext() 调用——一个用于提供的订阅者,一个用于转换中的doOnNext

有没有办法修改这个startWith 调用以发出我在doOnNext 中指定的任何内容?我正在使用 RxJava 1。

编辑:只是为了澄清一些,如果我跟踪发出的内容,我希望看到两件事。 Loading -&gt; Success。我实际看到的只是Success。如果我向 observable 提供订阅者,我会看到 Loading -&gt; Success -&gt; Success

【问题讨论】:

    标签: android rx-java


    【解决方案1】:

    startWith 应该在doOnNext 之前。

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

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

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

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

    另外,doOnNext 通常用于副作用,例如日志记录和排序,它们比真正的函数运算符更方便。

    【讨论】:

    • 如果我没有消费者,是不是用onErrorReturn处理?另外,我选择了doOnNext(),因为我有大约 6 个 observables,并且我想给每个 observables 提供相同的订阅者。我可以在班级级别定义订阅者,但我认为这已经足够了。
    • 另请注意:我必须在 doOnNext 之前移动 onErrorReturn 才能调用它。它现在可以工作,但现在肯定会有些困惑,无论我是否在这里实施了最佳实践。
    • @AdamMc331 onErrorReturn 只能在流中工作。如果发生错误并调用 OnErrorReturn 并且 doOnNext 是,则无论 doOnNext 是什么异常都会导致应用程序崩溃。此外,如果 onErrorReturn 是故障安全,它应该在 doOnNext 之前。
    猜你喜欢
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 2020-08-09
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    相关资源
    最近更新 更多