1. 程式人生 > >Android回顧系列——之HttpUrlConnect的使用

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

nco 留言 要求 idc stream extends value tput 回調

寫在前面:

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

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

  那麽,今天就來簡單介紹一下HttpUrlConnect的基本使用,和筆者自己做的一個小的工具類封裝。

先來學習原生的使用:

  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請求

       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

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

/**
 * 作者: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上,雖然水平一般,但開源精神還是可贊的嘛??

  

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