RuntimeException处理最佳实践

时间:2016-12-19 13:17:21

标签: android rx-java rx-kotlin

RuntimeExceptions应该表示编程错误,我希望我的应用程序在我的observables中的某些东西抛出RuntimeException时崩溃。

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

fun <T> Observable<T>.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") }
  )
}

但我对此表示怀疑。例如,很难偶尔使用此解决方案“捕获”特定的RuntimeExceptions。也许有一种众所周知的处理情况的方法,我只是不知道如何谷歌?

1 个答案:

答案 0 :(得分:1)

我认为在处理运行时(也就是未经检查)或常规(也称为已检查)异常时应该没有太大区别。这两天都被广泛使用,可以根据具体情况进行恢复或不恢复。

处理错误的反应方式是:

  1. 通过onErrorResumeNextonErrorReturn运营商;这些允许检查错误并可能从中恢复
  2. 通过retry*系列运营商;这些允许检查错误并可能通过重新订阅(例如重试网络呼叫)从中恢复
  3. 通过onError回拨您的订阅者;顺便说一句,如果你不提供这样的回调,错误将以常规Java方式重新抛出,因此你的程序崩溃
  4. 相关主题:How to handle different kinds of errors in Retrofit Rx onError without ugly instanceof

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

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

    示例代码

    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);
    

    所有异常都被RxJava捕获并传递到定义的路径。

    onError*运算符就像中间catch块一样。

    订阅者的onError回调就像顶级catch阻止一样。

    关于此主题的更多链接: