使用AsyncTask时应该如何处理HTTP响应代码?

时间:2015-12-14 22:49:50

标签: java android android-asynctask

我正在创建一个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.";
}

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

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

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

2 个答案:

答案 0 :(得分:2)

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

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

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

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

4)你可以像https://stackoverflow.com/a/6312491/5673694那样做。但是有一个不好的问题和一个'ehh'问题......

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

'ehh'问题(而且这更像是一个'被警告'的问题)...你可以让AsyncTask存储异常,但如果你让它成为一个静态的,这就有可能引起问题的问题您的AsyncTask类(Java中的Statics和Generics的工作方式与它们在C ++中的工作方式不同,在C ++中,您可以为模板化类的每个变体获得不同的类实现,但在Java中只有1个类文件,因此静态是在所有不同版本之间“共享”。)(注意:上面说'静态类',这里我说的是'那个类中的'静态变量')

答案 1 :(得分:0)

当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

    }