【问题标题】:How should I handle HTTP response codes when using AsyncTask?使用 AsyncTask 时应该如何处理 HTTP 响应代码?
【发布时间】:2016-03-20 14:02:30
【问题描述】:

我正在创建一个 android 应用程序,它接受用户输入,尝试使用指定的输入连接到 API url 并检索数据并显示它。现在我已经能够完成上述所有操作,但是如果用户输入了某些内容但它不存在,我的应用程序可能会因为 NPE(空指针异常)而崩溃。

我使用的 API 向我显示了可能发生的响应错误列表,但我不确定我应该如何处理或实现将这些响应错误考虑在内的功能。

目前我的扩展 AsyncTask 类具有以下参数:String、Void、JSONObject,以下代码是我的 doInBackground 方法中的内容.

URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();

int statusCode = urlConnection.getResponseCode();
switch (statusCode) {
    case 400:
    return "Error 400 - Bad request.";
    case 401:
    return "Error 401 - Unauthorized request.";
}

我无法返回字符串,因为我的 AsyncTask 参数返回 JSONObject。我可以更改它,让它返回一个字符串,但我认为这不是处理响应错误的正确逻辑方式。

现在,如果 API 响应代码是 404(未找到数据),我不希望应用程序崩溃,因为它无法返回 JSONObject,而是希望它继续到下一个片段并显示最少的信息。

那么当我的方法返回 JSONObject 时,我该如何处理响应错误?

【问题讨论】:

  • 创建一个可以作为回调的接口。创建 AsyncTask 时,将回调的新实例作为参数之一传递。在 AsyncTask 中保存对传递的回调的引用,并通过 onPostExecute 为 AsyncTask 处理响应。将响应码(状态码)传递给 onPostExecute() 并通过你创建的接口传递你想要的相关信息。如果需要可以提供代码示例

标签: java android android-asynctask


【解决方案1】:

你有几个选择(我说#1 是你最好的选择)

1) 创建一个自定义 JSON 对象,将状态码从后台部分传送到 UI(或其他调用线程)。然后只需检查从 asynctask 返回的 JSON 是否是“HTTP 结果 JSON”之一,而不是任何正常结果。 (基本上将您的“例外”/等从后台处理中包装到 JSON 中,并使用 JSON 传输您的返回消息以在任一条件下进行处理。)

2)您可以抛出异常(但我个人认为这是一个糟糕的设计,通常最好捕获异常然后在 onPostExecute() 中处理它们(通过 #1 等标志)

3) 您可以在 asyncTask 之外的某处设置一个标志来说明返回代码是什么(但这通常不是线程安全的。这意味着如果您的用户导致两个任务同时运行并且它们返回,这可能会很麻烦不同的顺序(或同时),您可能无法获得每个返回的“正确”值。)

4) 你可以像https://stackoverflow.com/a/6312491/5673694 所说的那样做。但是有 1 个坏问题和 1 个“ehh”问题......

坏问题:她的实现有内存泄漏问题。 Java 中的内部类在实例化时具有对其外部类实例的继承引用。这意味着,如果您的异步任务仍在运行,那么如果您出于某种原因退出您的应用程序/打来电话/等等,您的父类/(最有可能的活动)将无法被垃圾收集...因此,您的应用程序可以在很长一段时间内不应该占用系统内存。 (无论您的 asyncTask 运行多长时间(无限可能))要解决此问题,请将内部类设为静态,并对类实例使用 Wea​​kReference。 (这应该对 Android 中的所有内部类进行,它们与后台任务一起工作,例如处理程序等。)这个内存泄漏问题没有很好的记录,但存在,我们在 MOOC 中讨论它,我的博士顾问是教练和我是员工https://www.coursera.org/course/posacommunication

“ehh”问题(这更像是一个“被警告”问题)...您可以让 AsyncTask 存储异常,但是如果您将其设为静态,则可能会导致问题您的 AsyncTask 类(Java 中的静态和泛型与 C++ 中的工作方式不同,在 C++ 中,模板类的每个变体都有不同的类实现,但在 Java 中只有 1 个类文件,因此静态是在所有不同版本之间“共享”。)(注意:上面说的是“静态类”,这里我说的是“该类中的静态变量”)

【讨论】:

  • 感谢您的回复。我将使用第一个选项,看看它会把我带到哪里。
【解决方案2】:

statusCode不是200时可以返回null:

            URL url = new URL(params[0]);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            int statusCode = urlConnection.getResponseCode();

            if(statusCode!= 200){

                return null;

            }

然后在您的 postExecute 中,您可以检查该条件:

protected void onPostExecute(JSONObject result) {

    if (result == null) {

        // Inform the user something weird happened

    }
    else{

        // Do your normal condition with your JSON object
    }

您也可以尝试另一种方法:您可以返回一个 ArrayList,而不是返回 JSON 对象:

            ArrayList<Object>  result = new ArrayList<Object>();

            URL url = new URL(params[0]);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            int statusCode = urlConnection.getResponseCode();


            switch (statusCode) {

                case 200:
                   // Your code to build your JSON object
                   JSONObject yourJsonObject = ...
                   result.add("Ok");
                   result.add(yourJsonObject);
                   break;
                case 400:
                   result.add("Error 400 - Bad request.");
                   result.add(null);
                   break;
                case 401:
                   result.add("Error 401 - Unauthorized request.");
                   result.add(null);
                   break;
            }

然后在您的 postExecute 中检查 ArrayList 对象:

protected void onPostExecute(ArrayList<Object> result) {

    String message = (String) result.get(0);
    JSONObject yourJsonObject = (JSONObject) result.get(1);


    if (result == yourJsonObject) {

        // Inform the user something weird happened
        // Example: Toast the message

    }
    else{

        // Do your normal condition with your JSON object

    }

【讨论】:

  • 谢谢你,我会试试这个,看看它从哪里开始!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 2014-01-16
  • 1970-01-01
  • 2023-03-30
  • 2013-01-18
  • 2020-12-27
  • 1970-01-01
相关资源
最近更新 更多