RxJava2的UndeliverableException和已处理的流

时间:2018-02-09 18:46:25

标签: android rx-java2

我觉得我不了解RxJava2的错误处理方法。 (顺便说一下,我已经阅读了RxJava2 observable take throws UndeliverableException并且我理解会发生什么,但不确切地说为什么或者是否有更好的方式来处理它而不是我在下面讨论的内容。我也看到了RuntimeException thrown and not caught in RxJava2 Single after it has been disposed和它看起来并不完全相关。)

让我们说我有以下非常简化的例子:

val sub = Observable.fromCallable(callableThatCanReturnNull)
                    .subscribe({ println(it) }, { System.err.println(it) })

按顺序发生以下事件序列:

  1. sub.dispose()
  2. 该darn Callable返回null。
  3. 查看RxJava2源代码,我看到了:

    @Override
    public void subscribeActual(Observer<? super T> s) {
        DeferredScalarDisposable<T> d = new DeferredScalarDisposable<T>(s);
        s.onSubscribe(d);
        if (d.isDisposed()) {
            return;
        }
        T value;
        try {
            value = ObjectHelper.requireNonNull(callable.call(), "Callable returned null");
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            if (!d.isDisposed()) {
                s.onError(e);
            } else {
                RxJavaPlugins.onError(e);
            }
            return;
        }
        d.complete(value);
    }
    

    显然,在第一次d.isDisposed()支票和第二次d之间的某个时间,RxJavaPlugins.onError(e)被处理,因此我们点击eNullPointerExceptionObjectHelper.requireNonNull()(来自RxJavaPlugins.setErrorHandler())。如果我们没有用某些东西调用 GlobalErrorFilter errorFilter = new GlobalErrorFilter(BuildConfig.DEBUG /* alwaysCrash */); RxJavaPlugins.setErrorHandler(t -> { if (errorFilter.filter(t)) { // Crash in some cases throw new RuntimeException(t); } else { // Just log it in others Logger.e("RxError", t, "Ignoring uncaught Rx exception: %s", t.getLocalizedMessage()); } }); ,那么默认行为是抛出一个会导致应用程序崩溃的致命异常。这看起来很糟糕(tm)。我目前的做法如下:

    GlobalErrorFilter

    我的fromCallable考虑了这个UndeliverableException案例以及class GlobalErrorFilter(private val alwaysCrash: Boolean = false) { /** * Returns `true` if app should crash; `false` otherwise. Prefers to return `true`. */ fun filter(t: Throwable) = when { alwaysCrash -> true t is UndeliverableException -> false t.localizedMessage.contains("Callable returned null") -> false else -> true } } 。事实上,它看起来像这样:

    {{1}}

    这个感觉非常hackish。我想要的是告诉RxJava如果我处理了一个observable,我不关心是否(1)它发出新项目(2)它完成(3)它是onErrors。我只是不在乎。如果没有这个全局错误处理程序,有没有办法做到这一点?

0 个答案:

没有答案