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

写在前面:

  最近准备一个关于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上,虽然水平一般,但开源精神还是可赞的嘛😀

  

posted @ 2018-01-25 14:32  昕无旁骛  阅读(5691)  评论(2编辑  收藏  举报