【问题标题】:RxJava doOnError vs onErrorRxJava doOnError 与 onError
【发布时间】:2019-09-06 13:30:26
【问题描述】:

我正在尝试使用以下代码

initLocalSettingsIfNeed()
                            .andThen(initGlobalSettingsIfNeed(configuration))
                            .doOnComplete(callback::onSuccess)
                            .doOnError(throwable -> callback.onError(throwable.getLocalizedMessage()))
                            .subscribe();

但我有例外

由于缺少 onError 处理程序,异常未处理 subscribe() 方法调用。

我想我没有正确使用这些方法,我认为可以将doOnComplete doOnError 替换为subscribe() 方法中的观察者,我错了吗?

【问题讨论】:

  • 这是预期的行为。如果你想吞下错误,试试onErrorComplete
  • 不,我需要处理错误,这种方法是错误的,因为 doOnComplete() return new Single?
  • 不,不是因为这个。 doOnError 不能替代 onError

标签: android rx-java rx-java2


【解决方案1】:

试试这个

initLocalSettingsIfNeed()
    .andThen(initGlobalSettingsIfNeed(configuration))
    .subscribe({completed->
        callback.onSuccess()
    },{throwable->
        callback.onError(throwable.getLocalizedMessage())
    })

【讨论】:

  • 这种方法有效,但我有警告'未使用订阅的结果',因为我知道这需要在调用 onError 或 onComplete 时自动处理,有没有办法避免这个警告?
  • 您可以将它添加到例如 CompositeDisposable() 并在不再需要它之后将其丢弃。例如disposables.add(包装在上面的代码)然后disposables.dispose()
  • 但我没有在活动中使用它,我在没有生命周期的存储库中使用它
  • 使用 MVP 时应在 Model 中处理 Repository 使用逻辑,使用 MVVM 时应在 ViewModel 中处理
  • 这取决于你使用的是什么类型的 Observable,如果是例如 Single 是完全安全的,因为它只发射一次,所以无需处理就可以完全安全地使用它。那就是我用于存储库的东西
【解决方案2】:

关于您最初的问题,您必须知道doOnError 不是onError 的替代品。您在this blog 中有一个很好的简短解释:

实际上,它们之间有一个关键区别。 doOnError() 基本上只触发它的回调,然后将遇到的错误传递给下游。 因此,如果在 subscribe() 中没有 onError 回调就订阅了整个流,您的应用将因 OnErrorNotImplementedException 而崩溃。

另一方面,subscribe() 中的 onError 回调确实消耗了 错误。 这意味着,它会捕获错误,并让你处理它们 不会自己重新抛出错误。

关于您在一条评论中提到的警告:

这种方法有效,但我警告“订阅的结果” 未使用”,因为我知道这需要在 onError 或 onComplete 被调用,有没有办法避免这个警告? ——帕维尔·波利

一个好的方法是你在Repository 中的方法返回一个Observable,然后你可以在ViewModel 中订阅它们。然后,在每个 ViewModel 类中,您可以有一个带有 CompositeDisposable 的成员变量,您可以在其中将每个订阅的一次性添加到您的存储库返回的 Observables 中。最后,您应该重写onCleared 方法来处理存储在CompositeDisposable 中的所有一次性用品。

public class MyViewModel extends ViewModel {

    private MyRepository myRepository;
    private final CompositeDisposable disposables;

    @Inject
    public MyViewModel(MyRepository myRepository) {
        ...
        this.myRepository = myRepository;
        disposables = new CompositeDisposable();
        ...
    }

    public void callObservableInRepository() {
         disposables.add(myRepository.myObservable()
                              .subscribe(onSuccess -> {...} , onError -> {...}));
    }

    @Override
    protected void onCleared() {
        disposables.clear();
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 2019-03-28
    • 2018-02-20
    • 2019-12-22
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多