簡體   English   中英

使用AsyncTask時應如何處理HTTP響應代碼?

[英]How should I handle HTTP response codes when using AsyncTask?

我正在創建一個接受用戶輸入的android應用,嘗試使用指定的輸入連接到API網址,並檢索數據並顯示它。 現在,我已經能夠執行上述所有操作,但是有一個潛在的機會,如果用戶輸入了某些內容而又不存在,我的應用程序將由於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。 我可以對其進行更改,以便它確實返回String,但是我認為這不是處理響應錯誤的正確邏輯方法。

現在,如果API響應代碼為404(未找到數據),我不希望該應用程序崩潰,因為它無法返回JSONObject,而是希望它繼續進行下一個片段並顯示最少的信息。

那么,當我的方法返回JSONObject時,如何處理響應錯誤?

您有幾種選擇(我說#1是您最好的選擇)

1)創建一個自定義JSON對象,以將狀態代碼從后台部分傳送到UI(或其他調用線程)。 然后只要檢查從asynctask返回的JSON是否是“ HTTP結果JSON”之一,而不是正常結果即可。 (本質上是將您的“ exceptions” /等內容從JSON中的后台處理包裝起來,並使用JSON來傳輸您的返回消息以在任何一種情況下進行處理。)

2)您可以引發異常(但我個人認為這是不好的設計,通常更好地捕獲異常,然后在onPostExecute()中處理它們(通過#1這樣的標志)

3)您可以在asyncTask外部的某個位置設置一個關於返回代碼的標志(但這通常不是線程安全的。這意味着如果您的用戶導致一次運行兩個任務並且它們以不同的順序返回,這可能會很麻煩(或同時),則您可能無法獲得每次回報的“正確”值。)

4)您可以按照https://stackoverflow.com/a/6312491/5673694的說明進行操作。 但是有1個不良問題和1個“ ehh”問題...

不好的問題:她的實現存在內存泄漏問題。 Java中的內部類在實例化時對其外部類實例具有繼承引用。 這意味着,如果您的異步任務仍在運行,並且由於某種原因您退出了應用程序/打進了電話等,則您的父類/(最有可能的活動)將無法被垃圾回收。因此,您的應用程序應該在很長時間內不占用系統內存。 (多長時間(無限可能地)運行asyncTask)要解決此問題,請將內部類設為靜態,然后對類實例使用WeakRefernce <>。 (這應該在Android中處理后台任務的所有內部類(例如Handlers等)中完成。)此內存泄漏問題沒有得到充分記錄,但存在,我們在MOOC中討論,我的博士顧問是我是講師https://www.coursera.org/course/posacommunication

“ ehh”問題(這更多是“被警告”的問題)...您可以使AsyncTask存儲Exception,但是如果您在AsyncTask類中將其設置為靜態的,則可能會引起問題(Java中的靜態和泛型工作方式與C ++中的不同,在C ++中,對於模板化類的每個變體,您都有不同的類實現,但是在Java中只有1個類文件,因此靜態是“共享的”在所有不同版本之間。)(注意:上面說的是“靜態類”,這里我說的是“該類中的靜態變量”)

當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

    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM