RuntimeException处理最佳实践

RuntimeExceptions应该表示编程错误,并且当我的observables里面的东西抛出RuntimeException时,我希望我的应用程序崩溃。

做这个的最好方式是什么? 现在我正在考虑这个解决方案(这是Kotlin,但我希望这是可以理解的)

fun  Observable.subscribeCrashOnRuntimeException(onNext: (T) -> Unit, onError: (Throwable) -> Unit) { this.subscribe({ onNext(it) }, { e -> if (e is RuntimeException) { throw e } else { onError(e) } }) } fun usageExample() { val observable = Observable.just(1) observable.subscribeCrashOnRuntimeExceptions( { next -> Log.d("TAG", "next: $next") }, { e -> Log.d("TAG", "error: $e") } ) } 

但是我对此有所怀疑。 例如,很难偶尔用这个解决方案“捕捉”特定的RuntimeException。 也许有一个众所周知的方式来处理我只是不知道如何谷歌的情况?

我不认为在处理运行时(又称未选中)或常规(又称已检查)exception方面应该没有太大区别。 目前这两种方法都被广泛使用,根据具体情况可能是可以回收的。

处理错误的被动方式是:

  1. 通过onErrorResumeNextonErrorReturn运算符; 这些允许检查错误并且可能从错误中恢复
  2. 通过retry*操作员家族; 这些允许检查错误,并可能通过重新订阅(例如重试网络呼叫)
  3. 通过你的用户的onError回调; 顺便提一下,如果你不提供这样的回调,错误将以常规的Java方式重新抛出,所以你的程序崩溃

相关主题: 如何在不改变instanceof的情况下处理Retrofit Rx onError中的各种错误

还要注意以常规Java方式抛出exception的缺点:

  • 消息处理期间的调用堆栈与定义消息处理规则时的调用堆栈不同; 这意味着可能很难捕捉到这些exception,以及解释堆栈跟踪
  • 调度程序捕获的exception可能不会导致程序终止; 即你的程序可能最终挂在破碎的状态

示例代码

 Observable.fromCallable(() -> { ... if (ok) return "Success!"; else throw new RuntimeException("Failure at source"); }) .map(s -> { ... processing is bypassed in case of an error }) .map(s -> { ... if (...) return s.upperCase(); else throw new RuntimeException("Failure during processing"); }) .onErrorReturn(e -> { if (e.getMessage().contains("processing")) return "Recovered"; throw Exceptions.propagate(e); // let it continue as an error }) .subscribe(s -> println("got result: " + s), e -> println("got error: " + e); 

所有exception都被RxJava捕获,并沿着定义的路由传递。

onError*操作符就像中间catch块一样。

订户的onError回调就像顶级catch块一样。

关于这个问题的更多链接:

  • 在RxJava中处理错误
  • error handling操作符