如何处理Retrofit Rx onError中不同难度的错误

我想知道你的方式来处理不同types的错误(如httpexception,没有互联网连接exception等)在改进Rx onError,而不使用instanceof像这里提出的: 如何在RxJava或在这里处理 Retrofit 2中的网络错误 : Handle改造2 RX中的错误

在kotlin中,我将简单地为每种可投掷项目做一些扩展函数来做我想做的任何事情。

但是我不得不在项目中使用Java。 任何不错的建议?

是这样的构建某种error handling程序的方法:

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

好? 我知道这不是因为每次我需要处理另一个特定的错误,我不得不改变接口,所以这是违反开放原则。 但我找不出任何解决办法。

欢呼Wojtek

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

但是我想创建一个答案,不是因为这个原因,而是争辩说只有一个error handling程序在许多情况下实际上是可取的,而不是一个责任。 在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); } 

只有一个error handling程序使我们能够将许多types的exception组合在一起。 你可以在这段代码中看到,有一些不应该抛出的exception,只能是代码中的错误,以及我们需要处理的exception状态。 我觉得这个混乱,而且宁愿说:

 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. } 

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

避免链接的恰当的OOP方式是多态 。 您可以定义几个自定义的exception类,暴露出足以让单个处理程序处理的通用接口。

假设您需要将错误分为两组:可恢复和不可恢复。 那么你的基本exception类(或接口)应该有在每个子类中重写的抽象方法isRecoverable() 。 那么在你的处理程序中只有一个if if (e.isRecoverable()) { ... } else { ... }

缺点是你必须把所有的标准exception包装到自定义的exception中(你必须抓住它们)。

不过,正确的选择将很大程度上取决于你的任务。