天天看點

網絡程式設計的最佳實踐

目前你已經掌握了 HttpURLConnection的用法,知道了如何發起 HTTP請 求

​​​HttpURLConnection使用​​​

以及解析伺服器傳回的資料

​​​解析 XML格式資料​​​

​​​解析JSON資料​​

其實之前我們的寫法其實是很有問題的。 因為一個應用程式很可能會在許多地方都使用到網絡功能,而發送 HTTP請求的代碼基本都 是相同的,如果我們每次都去編寫一遍發送 HTTP請求的代碼,這顯然是非常差勁的做法

通常情況下我們都應該将這些通用的網絡操作提取到一個公共的類裡,并提供一 個靜态方法,當想要發起網絡請求的時候隻需簡單地調用一下這個方法即可。比如使用如下 的寫法:

public class HttpUtil {
    public static String sendHttpRequest(String address){
        HttpURLConnection connection = null;
        StringBuilder response = new StringBuilder();
        try {
            URL url = new URL(address);
            connection = (HttpURLConnection)url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(8000);
            connection.setReadTimeout(8000);
            connection.setDoInput(true);
            connection.setDoOutput(true);

            InputStream in = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = reader.readLine())!=null){
                response.append(line);
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response.toString();
    }
}      

以後每當需要發起一條 HTTP請求的時候就可以這樣寫:

String address = "https://www.baidu.com";
                String response = HttpUtil.sendHttpRequest(address);      

在擷取到伺服器響應的資料後我們就可以對它進行解析和處理了。但是需要注意,網絡 請求通常都是屬于耗時操作,而 sendHttpRequest()方法的内部并沒有開啟線程,這樣就有可 能導緻在調用 sendHttpRequest()方法的時候使得主線程被阻塞住

那麼遇到這種情況應該怎麼辦呢?其實解決方法并不難,隻需要使用 Java的回調機制 就可以了,下面就讓我們來學習一下回調機制到底是如何使用的

首先需要定義一個接口,比如将它命名成 HttpCallbackListener

public interface HttpCallbackListener {
    void onFinish(String response);
    void onError(Exception e);
}      

我們在接口中定義了兩個方法,onFinish()方法表示當伺服器成功響應我們請 求的時候調用,onError()表示當進行網絡操作出現錯誤的時候調用

這兩個方法都帶有參數, onFinish()方法中的參數代表着伺服器傳回的資料,而 onError()方法中的參數記錄着錯誤的 詳細資訊

接着修改 HttpUtil中的代碼

public class HttpUtil {
    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL(address);
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    connection.setDoOutput(true);
                    connection.setDoInput(true);

                    InputStream in = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine())!=null){
                        response.append(line);
                    }
                    if(listener != null){
                        listener.onFinish(response.toString());
                    }
                } catch (Exception e) {
                    if(listener != null){
                        listener.onError(e);
                    }
                }
            }
        }).start();
    }
}      

我們首先給 sendHttpRequest()方法添加了一個 HttpCallbackListener參數,并在方法的内 部開啟了一個子線程,然後在子線程裡去執行具體的網絡操作

注意子線程中是無法通過 return語句來傳回資料的,是以這裡我們将伺服器響應的資料傳入了 HttpCallbackListener的 onFinish()方法中,如果出現了異常就将異常原因傳入到 onError()方法中

現在 sendHttpRequest()方法接收兩個參數了,是以我們在調用它的時候還需要将 HttpCallbackListener的執行個體傳入,如下所示:

private void sendRequestWithURLConnection() {
        String address = "https://www.baidu.com";
        HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
            @Override
            public void onFinish(String response) {
                //這裡根據傳回内容執行具體的邏輯
                Message message = new Message();
                message.what = SHOW_RESPONSE;
                //将伺服器傳回的結果存放到Message中
                message.obj = response;
                handler.sendMessage(message);
            }

            @Override
            public void onError(Exception e) {
                //這裡對異常情況進行處理
            }
        });
    }      

這樣的話,當伺服器成功響應的時候我們就可以在 onFinish()方法裡對響應資料進行處 理了,類似地,如果出現了異常,就可以在 onError()方法裡對異常情況進行處理

繼續閱讀