Android回顧系列——之HttpUrlConnect的使用

寫在前面:

  最近準備一個關於Android的比賽。因爲賽項要求,不得使用第三方工具、框架;故最近來溫習一下Google官方提供的原始API的使用。api

  說實話,用慣了第三方的庫,再回過頭來用原生的api的確使人以爲麻煩,不過也不能僅僅依賴於各類層出不窮的框架和庫,掌握相對底層的核心點,纔是競爭力的來源。而且用了第三方的庫以後再來看原生,不經意間就會有好的思路產生。網絡

  那麼,今天就來簡單介紹一下HttpUrlConnect的基本使用,和筆者本身作的一個小的工具類封裝。app

先來學習原生的使用:

  Ps:  解釋以註釋形式寫在代碼中框架

  * GET請求異步

        new Thread(new Runnable() {
            @Override
            public void run() {
                //接口地址
                String url_path = "http://223.111.182.5:8080/logistics/goods/myOffer";
                try{
                    //使用該地址建立一個 URL 對象
                    URL url = new URL(url_path);
                    //使用建立的URL對象的openConnection()方法建立一個HttpURLConnection對象
                    HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
                    /**
                     * 設置HttpURLConnection對象的參數
                     */
                    // 設置請求方法爲 GET 請求
                    httpURLConnection.setRequestMethod("GET");
                    //使用輸入流
                    httpURLConnection.setDoInput(true);
                    //GET 方式,不須要使用輸出流
                    httpURLConnection.setDoOutput(false);
                    //設置超時
                    httpURLConnection.setConnectTimeout(10000);
                    httpURLConnection.setReadTimeout(1000);
                    //鏈接
                    httpURLConnection.connect();
                    //還有不少參數設置 請自行查閱

                    //鏈接後,建立一個輸入流來讀取response
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),"utf-8"));
                    String line = "";
                    StringBuilder stringBuilder = new StringBuilder();
                    String response = "";
                    //每次讀取一行,若非空則添加至 stringBuilder
                    while((line = bufferedReader.readLine()) != null){
                        stringBuilder.append(line);
                    }
                    //讀取全部的數據後,賦值給 response
                    response = stringBuilder.toString().trim();
                    Utils.log(" 打印響應 " + response);
                    final String finalResponse = response;
                    //切換到ui線程更新ui
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            result.setText(finalResponse);
                        }
                    });
                    bufferedReader.close();
                    httpURLConnection.disconnect();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();

  * POST請求ide

       new Thread(new Runnable() {
            //建立HttpURLConnection變量
            HttpURLConnection httpURLConnection = null;
            //建立PrintWriter變量,用於向HttpURLConnection寫入請求參數
            PrintWriter printWriter = null;
            //建立BufferedReader,來接收相應數據流
            BufferedReader bufferedReader = null;
            //定義緩衝
            StringBuilder stringBuilder = new StringBuilder();
            //定義line讀取一行數據
            String line = "";
            //定義接口地址
            String url_path = "http://xxx.xxx.xxx.xxx:8080/logistics/goods/bidCount";
            //模擬參數
            String para = "goodId=14";
            String response = "";
            @Override
            public void run() {
                try{
                    URL url = null;
                    if(url_path.equals("")){
                        return;
                    }
                    //使用接口地址初始化URL對象
                    url = new URL(url_path);
                    //使用URL對象建立HttpURLConnection對象
                    httpURLConnection = (HttpURLConnection) url.openConnection();
                    //設置相應參數
                    httpURLConnection.setDoInput(true);
                    httpURLConnection.setDoOutput(true);    //能夠建立輸出流,將請求參數寫入
                    httpURLConnection.setRequestMethod("POST"); //請求方式爲POST
                    //將請求參數寫入鏈接的輸出流
                    printWriter = new PrintWriter(httpURLConnection.getOutputStream());
                    printWriter.print(para);
                    printWriter.flush();
                    //獲取響應結果
                    bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),"utf-8"));
                    while ((line = bufferedReader.readLine()) != null){
                        stringBuilder.append(line);
                    }
                    response = stringBuilder.toString().trim();
                    //切換主線程更新ui
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            result.setText(response);
                        }
                    });
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    try{
                        /**
                         * 關閉鏈接/流
                         */
                        if(printWriter != null){
                            printWriter.close();
                        }
                        if(bufferedReader != null){
                            bufferedReader.close();
                        }
                        if(httpURLConnection != null){
                            httpURLConnection.disconnect();
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }).start();

 下面貼一個本身寫的一個Post請求工具類:

  Ps:爲何不封裝的更完善些呢?好比支持支持Get請求、支持自定義Http頭部各參數設置,異步消息部分採用Handle或AsynTask。其實剛剛說的這些包括尚未想到的,均可以添加上去,只是筆者時間緊迫,因此如下的工具類只提供Post方式的請求。函數

  工具類支持:工具

    •   自定義參數(傳參時,只要傳入相對應的map)
    •   支持接口回調,在回調方法內寫結果處理邏輯
    •   簡單的線程控制,開發者不須要手動實現線程切換
    •   簡單易用的API

  下面貼工具類代碼,和簡單的使用方法:post

/**
 * 做者:LiChangXin
 * Created by haiyang on 2018/1/25.
 * 簡介:
 * 1.自定義參數(傳參時,只要傳入相對應的map)
 * 2.支持接口回調,在回調方法內寫結果處理邏輯
 * 3.簡單的線程控制,開發者不須要手動實現線程切換
 * 4.簡單易用的API
 */

public class XykjHttpPost extends Thread{
    /**
     * 經過構造函數
     * 賦值:
     * url - 接口地址
     * form - 請求參數(map)
     * xykjHttpCall - 回調接口
     * mactivity - 基於activity的runOnUiThread()方法的線程控制
     */
    private String url = "";
    private Map<String,String> form;
    private XykjHttpCall xykjHttpCall = null;
    private Activity mactivity;
    //下面這些 與以前的例子相同
    private HttpURLConnection connection = null;
    private PrintWriter pw = null;
    private BufferedReader bufferedReader = null;
    private String line = null;
    private StringBuilder response_cache = new StringBuilder();
    private String response = null;
    private String parameter = null;
    //構造函數
    public XykjHttpPost(XykjHttpCall xykjHttpCall,String url_p, Map<String,String> form_p,
                        Activity activity){
        url = url_p;
        form = form_p;
        this.xykjHttpCall = xykjHttpCall;
        mactivity = activity;
    }
    
    @Override
    public void run() {
        Utils.log("XYKJHTTPPOST : " + "Thread@run() 方法開始執行");
        try{
            if(url.equals("") || url == null){
                //若url爲空,結束執行
                Utils.log("XYKJHTTPPOST : " + "無請求參數");
                return;
            }
            URL url_path = new URL(url.trim());
            connection = (HttpURLConnection) url_path.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setRequestMethod("POST");
            //獲取鏈接
            connection.connect();
            if(!form.isEmpty() && form != null){
                //獲取鏈接輸出流,並寫入表單參數
                pw = new PrintWriter(connection.getOutputStream());
                parameter = formDataConnect(form);
                pw.print(parameter);
                pw.flush();
            }
            //獲取響應 輸入流
            bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            while ((line = bufferedReader.readLine()) != null){
                response_cache.append(line);
            }
            response = response_cache.toString().trim();
            Utils.log("XYKJHTTPPOST : RESPONSE -> " + response);
            mactivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(response != null && !response.equals("")){
                        xykjHttpCall.success(response);
                    }else {
                        xykjHttpCall.error("Response爲空");
                    }
                }
            });
        }catch (Exception e){
            mactivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    xykjHttpCall.error("XYKJHTTPPOST : 網絡請求/解析異常");
                }
            });
            Utils.log("XYKJHTTPPOST : 網絡請求/解析異常");
            e.printStackTrace();
        }finally {
            try{
                if(pw != null){
                    pw.close();
                }
                if(bufferedReader != null){
                    bufferedReader.close();
                }
                if(connection != null){
                    connection.disconnect();
                }
            }catch (Exception e){
                mactivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        xykjHttpCall.error("XYKJHTTPPOST : 關閉鏈接/流異常");
                    }
                });
                Utils.log("XYKJHTTPPOST : 關閉鏈接/流異常");
                e.printStackTrace();
            }
        }
    }


    /**
     * 參數轉換函數
     * map -> http[post] 參數
     * @param form_data
     * @return
     */
    public String formDataConnect(Map<String,String> form_data){
        StringBuilder url_form = new StringBuilder();
        //遍歷map,按照url參數形式拼接
        for(String key:form_data.keySet()){
            if(url_form.length() != 0){
                //從第二個參數開始,每一個參數key、value前添加 & 符號
                url_form.append("&");
            }
            url_form.append(key).append("=").append(form_data.get(key));
        }
        return url_form.toString();
    }

    /**
     *  定義回調接口
     */
    public interface XykjHttpCall {
        void success(String response);
        void error(String error_message);
    }

    /**
     * 線程啓動
     * 執行請求
     */
    public void request(){
        this.start();
    }

}

 * 使用方法:學習

  先上業務場景,是一個用戶的登陸操做,收集 手機號碼和密碼 後進行post請求驗證。

最後調用該對象的request()方法,便可啓動post請求。

 * 效果:

  

   Ok,今天的養分目標達成。

  有什麼問題或者有好的想法的能夠在評論裏留言,筆者會在第一時間解答。

  將來的話,若是筆者繼續搞Android,會慢慢來豐富這個工具類,屆時會開源到Github上,雖然水平通常,但開源精神仍是可讚的嘛😀

相關文章
相關標籤/搜索