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上,虽然水平一般,但开源精神还是可赞的嘛😀
知道自己想要什么的人,每一步都在路上。