处理HTTP错误调用的最佳实践

4
我将这个问题发布到了Android开发者群组,但我也想在这里发布,以便其他可能遇到类似设计问题的人能够获得帮助:
我正在寻找一种处理HTTP错误的成语或范例。
基本上,我有一个在后台线程中运行的AsyncTask,调用了我自己的静态方法executeRequest()。
这全部都是在doInBackground()部分完成的。executeRequest()可能会抛出两种类型的异常:所有通信错误都会抛出IOException,而ServerErrorResponse异常则是我的自定义异常。如果例如客户端向服务器发送了一些错误内容,整个HTTP工作正常,但服务器报错(也许是因为我传递了无效的参数或ID),就会出现这种情况。
所以,我所做的就是将结果包装在“结果对象”中。
在onPostExecute()中,我检查结果是否失败,然后尝试在UI线程中处理它。然而,现在我必须开始进行
Exception e = result.getException();
if (e != null) {
  if (e instanceof IOException) { //network error
   //handle network error here
 } else if (e instanceof ServerErrorResponseException) {
   //handle server error response here
}

你可能已经注意到这变得很烦人了,每次出现新的异常都需要使用 instanceof 进行检查。有没有什么方法或设计可以避免这种情况?我希望在处理异常时能在 UI 线程中进行,以防需要向用户显示对话框或其他内容。

有任何想法吗?

2个回答

3
Exception e = result.getException();
if (e != null) {
  try {
    throw e;
  } catch (IOException ex) {
    //handle network error here
  } catch (ServerErrorResponseException ex) {
    //handle server error response here
  } catch (Exception ex) {
    //handle RuntimeException and others here
    //(You weren't just going to ignore them, were you?)
  }
}

2
你还可以看一下java.util.concurrent包中的ExecutorService。它使得处理后台任务的异常非常简单;如果一个任务抛出了异常,尝试从相关的Future获取结果时会抛出异常而不是获取结果。因此,你的应用程序不需要进行显式的“是否有错误”检查。 - erickson
是的,Android的AsyncTask使用ExecutorService来实现。让我再回顾一些内容,然后我会将此响应标记为答案。除了重新抛出和捕获之外,您还能想到其他方法吗? - dnkoutso
这不是唯一的方法(使用instanceof测试也可以),但我认为这是最好的方法。这是一种常见的模式,在其他API中(间接)使用。 - erickson

2

这只是其中一个选项:

创建一个类似以下界面的接口:

public interface ResultReceiver {
  public void onSuccess(YourClass object);
  public void onError(Exception err);
  //alternatives to the former:
  public void onNetworkError(IOException err); //maybe the parameter is optional?
  public void onServerProblem(ServerErrorResponseException err);
}

现在,在您的onPostExecute中做一些类似于以下内容的操作。
result.handleWith(this); //I'm assuming your activity implements ``ResultReceiver`` interface

如果您愿意,可以在活动之外创建结果处理程序(这种选项更好,以避免在活动之间重复代码)。最后,是“handleWith”实现:
public void handleWith(ResultReceiver handler){ 
  Exception e = result.getException();
  if (e != null) {
    if (e instanceof IOException) { //network error
     handler.onNetworkError(e);
   } else if (e instanceof ServerErrorResponseException) {
     handler.onServerProblem(e);
  } else {
     handler.onSuccess(this);
  }

}

Pedro,感谢您的回复,但这不是我要找的。我想避免一直使用instanceof来检查错误类型的模式。如果出现新的异常类型,我必须添加另一个elseif语句并更新接口。 - dnkoutso
通常情况下,我会有3或4种情况:成功、网络错误、服务器错误和可能的意外错误。通常我会分别处理这些3(或4)种情况。进一步的错误应该属于这些选项之一,在这些情况下,我会发送一些字符串或代码,提供关于应该显示哪个消息的信息。如果你能做到这一点,就不必创建其他类型的错误。 - Pedro Loureiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接