android - 如何在没有丑陋的 instanceof 的情况下处理 Retrofit Rx onError 中的不同类型的错误

标签 android rx-java retrofit2 onerror

我想知道您在改造 Rx onError 时如何处理不同类型的错误(如 http 异常、无互联网连接异常等),而不使用 instanceof,就像这里建议的那样:How to handle network errors in Retrofit 2 with RxJava或此处:Handle errors in Retrofit 2 RX

在 kotlin 中,我将简单地为每种 throwable 做一些扩展函数来做我想做的事。

但是我在项目中被迫使用Java。有什么好的建议吗?

是构建某种错误处理程序的方法,如下所示:

public interface ErrorHandler {
    void handleError(Exception e);
    void handleError(HttpException e);
    void handleError(NullPointerException npe);

}

好吗?我知道这不是因为每次我需要处理另一个特定错误时我都被迫更改接口(interface),所以这违反了开闭原则。但我想不出任何解决方案。

干杯 沃伊泰克

最佳答案

编译器决定调用哪个方法,而不是 VM。因此,除非您先检查 instanceof 并将参数转换为正确的类型,否则您描述的类不会解决问题。否则你每次都会得到 handleError(Exception e) 。

但我想创建一个答案不是出于这个原因,而是为了争辩说在许多情况下实际上只有一个错误处理程序是可取的,而不是一种责任。在 Java 中,我们经常会遇到这样糟糕的情况:

    catch (NoSuchAlgorithmException e) {
        throw new IllegalStateException("No such algorithm: RSA?", e);
    }
    catch (NoSuchProviderException e) {
        throw new IllegalStateException("No such provider: " + ANDROID_KEYSTORE_ID, e);
    }
    catch (InvalidAlgorithmParameterException e) {
        throw new IllegalStateException("Bug setting up encryption key for user credentials: ", e);
    }
    catch (KeyStoreException e) {
        throw new IllegalStateException("Bug setting up encryption key for user credentials: ", e);
    }
    catch (IOException e) {
        Log.w(TAG, "Exception setting up keystore for user creds. They won't be stored.", e);
    }
    catch (CertificateException e) {
        Log.w(TAG, "Exception setting up keystore for user creds. They won't be stored.", e);
    }

只有一个错误处理程序使我们能够将多种类型的异常集中在一起。您可以在这段代码中看到,存在永远不应抛出的异常、实际上只能由代码中的错误导致的异常以及我们需要处理的合法异常状态。我觉得这很乱,我更愿意说:

if (e instanceof NoSuchAlgorithmException || e instanceof NoSuchProviderException)  { 
    Log.wtf(TAG, "What the heck is this?", e);
    throw new IllegalStateException("This is some kind of weird bug", e);
}
else if (e instanceof IOException || e instanceof CertificateException) {
    // This can happen sometimes, track event in analytics and perhaps 
    // try some alternative means of credential storage.
} 
else {
    // At least here the app won't crash if some unexpected exception occurs,
    // since we're trapping everything.
} 

我认为能够将意外故障集中在一起并以比让应用程序崩溃更友好的方式处理它们并不是一件坏事。即使它只是一个错误,最好在幕后的分析框架中跟踪它,而不是将用户轰炸出应用程序。 Android 应用程序中的许多崩溃实际上是完全可以恢复的,但我们不会在每个 try/catch 语句中都捕获 Throwable,因为它有很多额外的代码。

关于android - 如何在没有丑陋的 instanceof 的情况下处理 Retrofit Rx onError 中的不同类型的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38052919/

相关文章:

java - RxJava 一个 Retrofit Network 调用订阅

android - 用户选择返回时的事件?

Android Phonegap 滚动不工作

android - Mockito MockApi 返回 null

java - RxJava Flowable 缓存到单一死锁

android - 使用 Retrofit 进行两次 API 调用以形成一个对象

java - RxJava Flowable.create(),如何尊重subscribeOn()线程

java - 在 toast 上显示整数

android - RXJava Android - 创建另一个可观察对象所需的可观察结果

android - 使用 Retrofit 在 URL 中获取带有 `&` 附加参数的请求