okhttp 使用完全解析

前言

一直以来,我们都在寻找更好用的网络框架,很多大牛们也一直致力于网络框架的设计.只为了一个目标:简单易学,但是功能却强大,性能也不错.okhttp正是这样子的一个框架,越来越多的人使用它作为网络请求的框架,它的出现也将近一年了,那么现在就让我们来学习学习吧,就基于最新的版本进行讲解

本篇博客使用okhttp的同步方法来讲解,自己开启子线程,okhttp里面也有异步的处理,和以前的异步处理框架的使用时非常类似的,没有返回值,需要传入一个接口,作为回调,方法是void enqueue(Callback responseCallback);


环境要求

支持Android 2.3及其以上版本,要求Java JDK1.7以上


简单的一个get请求

首先添加依赖:compile 'com.squareup.okhttp3:okhttp:3.3.1'

xml布局

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:paddingBottom="@dimen/activity_vertical_margin"  
  7.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  8.     android:paddingRight="@dimen/activity_horizontal_margin"  
  9.     android:paddingTop="@dimen/activity_vertical_margin"  
  10.     tools:context="com.example.cxj.demotest.MainActivity">  
  11.   
  12.     <Button  
  13.         android:layout_width="match_parent"  
  14.         android:text="点我"  
  15.         android:onClick="clickView"  
  16.         android:layout_height="wrap_content" />  
  17. </RelativeLayout>  
就是一个按钮

Activity中代码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MainActivity extends AppCompatActivity implements Runnable {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         setContentView(R.layout.activity_main);  
  6.     }  
  7.   
  8.     public void clickView(View view) {  
  9.   
  10.         new Thread(this).start();  
  11.     }  
  12.   
  13.     @Override  
  14.     public void run() {  
  15.         try {  
  16.             //请求的网址  
  17.             String url = "https://publicobject.com/helloworld.txt";  
  18.   
  19.             //创建网络请求框架  
  20.             OkHttpClient client = new OkHttpClient();  
  21.   
  22.             //创建请求对象  
  23.             Request request = new Request.Builder()  
  24.                     .url(url)  
  25.                     .build();  
  26.   
  27.             //执行请求返回结果  
  28.             Response response = client.newCall(request).execute();  
  29.   
  30.             //打印返回的结果,以字符串的形式  
  31.             System.out.println("result = " + response.body().string());  
  32.   
  33.         } catch (Exception e) {  
  34.             System.out.println("请求失败" + e.getMessage() + "," + e.getCause());  
  35.         }  
  36.   
  37.     }  
  38. }  

运行效果


可以看到我们请求是成功的,请求的内容被打印在控制台上,而我从使用上面可以看出来,okhttp框架并不是一个异步的请求框架,如果你直接在主线程中请求,程序会挂掉

post请求之提交普通数据

post请求我们知道可以做get请求的事情,也可以做get请求做不到的提交文件,这里先演示提交普通数据
由于post请求没有可以测试的接口,所以这里博主自己弄了一个测试接口,使用springMvc快速搭建的一个测试项目,项目名称为Test
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @RequestMapping("test")  
  2. @Controller  
  3. public class TestController {  
  4.   
  5.     /** 
  6.      * 响应post请求 
  7.      *  
  8.      * @param request 
  9.      * @param response 
  10.      * @throws IOException 
  11.      */  
  12.     @RequestMapping(value = "testPost")  
  13.     public void testPost(HttpServletRequest request, HttpServletResponse response, //  
  14.             String name, String pass) throws IOException {  
  15.         System.out.println("name = " + name);  
  16.         System.out.println("pass = " + pass);  
  17.         response.getWriter().println("hello");  
  18.     }  
  19.   
  20. }  

这里可以响应一个请求,请求地址是:http://localhost:8080/Test/test/testPost

这里不懂的童鞋可以不必过多深究,这里只是告诉大家这里有一个测试接口,请求可以接受两个参数name和pass
那我们就开始测试post请求吧
由于博主是开模拟器测试post请求,所以这里的localhost要跟换成对应的ip才可行,你们自己测试的时候也是,一定要记得更换localhost为对应的ip地址

那我们run方法中的代码就有所改变了
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public void run() {  
  3.     try {  
  4.         //请求的网址  
  5.         String url = "http://192.168.1.103:8080/Test/test/testPost";   
  6.         //192.168.1.103是我电脑的ip,如果你看到这段代码,那么这个ip请你自己更换成你自己的  
  7.   
  8.         //创建网络请求框架  
  9.         OkHttpClient client = new OkHttpClient();  
  10.   
  11.         FormBody.Builder builder = new FormBody.Builder();  
  12.         builder.add("name","小金子");  
  13.         builder.add("pass","123");  
  14.   
  15.         //构建了一个请求体  
  16.         FormBody formBody = builder.build();  
  17.   
  18.         //创建请求对象  
  19.         Request request = new Request.Builder()  
  20.                 .url(url)  
  21.                 .post(formBody)  
  22.                 .build();  
  23.   
  24.         //执行请求返回结果  
  25.         Response response = client.newCall(request).execute();  
  26.   
  27.         //打印返回的结果,以字符串的形式  
  28.         System.out.println("result = " + response.body().string());  
  29.   
  30.     } catch (Exception e) {  
  31.         System.out.println("请求失败" + e.getMessage() + "," + e.getCause());  
  32.     }  
  33.   
  34. }  


可以看到我们更改的代码无非就是多了一个请求体,我们接触web的童鞋都应该知道,post请求的数据是放在请求体中的,所以这里需要构建一个请求体对象,而普通字段的请求体,通过FormBody.Builder构建即可

请求提交后的效果,这里在服务器上看提交上来的数据


这里可以很清楚的看到两个参数被提交上来,所以普通数据的表单可以利用FormEncodingBuilder就可以完成需求啦

post请求提交json格式的数据

这个问题总结一下其实就是两点:
1.提交的数据不是键值对的形式,而是一个json格式
2.提交的请求标识请求的类型,这个是需要我们自己去实现的
而对于一个请求来说,json格式的请求无非就是提交一个字符串,构建一个RequestBodt,所以可以这样子做
[java]  view plain  copy
  1. public class JsonRequestParameter {  
  2.       
  3.     private JSONObject jb = new JSONObject();  
  4.   
  5.     private static JsonRequestParameter jsonRequestParameter = null;  
  6.   
  7.     /** 
  8.      * 构造函数私有化 
  9.      */  
  10.     private JsonRequestParameter() {  
  11.     }  
  12.   
  13.     /** 
  14.      * 获取单利的对象 
  15.      * 
  16.      * @return 
  17.      */  
  18.     public static JsonRequestParameter getInstance() {  
  19.         if (jsonRequestParameter == null) {  
  20.             jsonRequestParameter = new JsonRequestParameter();  
  21.         }  
  22.         return jsonRequestParameter;  
  23.     }  
  24.   
  25.     /** 
  26.      * 添加参数 
  27.      * 
  28.      * @param key 
  29.      * @param value 
  30.      */  
  31.     public JsonRequestParameter addParameter(String key, String value) {  
  32.         try {  
  33.             jb.put(key, value);  
  34.         } catch (Exception e) {  
  35.         }  
  36.         return this;  
  37.     }  
  38.   
  39.     public JsonRequestParameter addParameter(String key, int value) {  
  40.         try {  
  41.             jb.put(key, value);  
  42.         } catch (Exception e) {  
  43.         }  
  44.         return this;  
  45.     }  
  46.   
  47.     public JsonRequestParameter addParameter(String key, String[] values) {  
  48.         try {  
  49.             JSONArray ja = new JSONArray();  
  50.             for (int i = 0; values != null && i < values.length; i++) {  
  51.                 if (values[i] != null) {  
  52.                     ja.put(values[i]);  
  53.                 }  
  54.             }  
  55.             jb.put(key, ja);  
  56.         } catch (Exception e) {  
  57.         }  
  58.         return this;  
  59.     }  
  60.   
  61.     /** 
  62.      * 构建出json字符串 
  63.      * 
  64.      * @return 
  65.      */  
  66.     public RequestBody build() {  
  67.         String s = jb.toString();  
  68.         System.out.println("json请求体:" + s);  
  69.         jb = new JSONObject();  
  70.         RequestBody requestBody = RequestBody.create(Constant.mediaType, s);  
  71.         return requestBody;  
  72.     }  
  73.   
  74. }  
[java]  view plain  copy
  1. /** 
  2.   * 请求的时候的类型 
  3.   */  
  4.  public static final MediaType mediaType = MediaType.parse("application/json; charset=utf-8");  


通过这段代码就可以构建一个json格式的RequestBody,然后就可以像FormBody一样使用啦!
[java]  view plain  copy
  1. RequestBody body = JsonRequestParameter.getInstance()  
  2.         .addParameter("name""小金子")  
  3.         .addParameter("pass"123)  
  4.         .build();  
  5.   
  6. //创建请求对象  
  7. Request request = new Request.Builder()  
  8.         .url("http://......")  
  9.         .post(body)  
  10.         .build();  
  11.   
  12. //执行请求返回结果  
  13. Response response = client.newCall(request).execute()  
上面就是一个使用的范例

post请求之文件上传


文件上传这个功能其实真是无处不在,无论在手机端还是网页端,或多或少都会接触到文件上传的功能,这里主要对利用okhttp进行文件上传对一个详细的讲解
首先你得确定你的测试机有一个可用的文件可供你上传,有些模拟器SD卡不可用的,所以请先检查你有一个可用的测试文件然后再往下看

由于需要测试文件的上传,那么服务器添加一个测试post文件的代码
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @RequestMapping("test")  
  2. @Controller  
  3. public class TestController {  
  4.   
  5.     /** 
  6.      * 响应post请求 
  7.      *  
  8.      * @param request 
  9.      * @param response 
  10.      * @throws IOException 
  11.      */  
  12.     @RequestMapping(value = "testPost")  
  13.     public String testPost(HttpServletRequest request, HttpServletResponse response, //  
  14.             String name, String pass) throws IOException {  
  15.         System.out.println("name = " + name);  
  16.         System.out.println("pass = " + pass);  
  17.         return "success";  
  18.     }  
  19.   
  20.     @RequestMapping(value = "uploadFile")  
  21.     public String testPost(@RequestParam("file") MultipartFile file, String name, String pass) {  
  22.   
  23.         System.out.println("file-name = " + file.getOriginalFilename());  
  24.         System.out.println("file-length = " + file.getSize());  
  25.   
  26.         System.out.println("name = " + name);  
  27.         System.out.println("pass = " + pass);  
  28.   
  29.         return "success";  
  30.     }  
  31.   
  32. }  

可以看到testPost就是我们响应上传文件的方法

Activity中的代码如下
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public void run() {  
  3.     try {  
  4.         //请求的网址  
  5.         String url = "http://192.168.1.103:8080/Test/test/uploadFile";  
  6.         //192.168.1.103是我电脑的ip,如果你看到这段代码,那么这个ip请你自己更换成你自己的  
  7.   
  8.         //需要上传的文件  
  9.         File f = new File(Environment.getExternalStorageDirectory(), "address.db");  
  10.           
  11.         //创建网络请求框架  
  12.         OkHttpClient client = new OkHttpClient();  
  13.   
  14.         //创建文件部分的请求体对象  
  15.         RequestBody fileRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), f);  
  16.           
  17.         //创建总的请求体对象,包含普通键值对和文件数据  
  18.         RequestBody requestBody = new MultipartBody.Builder()  
  19.                 .setType(MultipartBody.FORM)  
  20.                 //普通字段的部分  
  21.                 .addFormDataPart("name","小金子")  
  22.                 .addFormDataPart("pass","123")  
  23.                 //添加文件部分  
  24.                 .addFormDataPart("file",f.getName(),fileRequestBody)  
  25.                 .build();  
  26.   
  27.         //创建请求对象  
  28.         Request request = new Request.Builder()  
  29.                 .addHeader("Connection","keep-alive")  
  30.                 .url(url)  
  31.                 .post(requestBody)  
  32.                 .build();  
  33.   
  34.         //执行请求返回结果  
  35.         Response response = client.newCall(request).execute();  
  36.   
  37.         //打印返回的结果,以字符串的形式  
  38.         System.out.println("result = " + response.body().string());  
  39.   
  40.     } catch (Exception e) {  
  41.         System.out.println("请求失败" + e.getMessage() + "," + e.getCause());  
  42.     }  
  43.   
  44. }  

在上述代码中,涉及到文件的类型,这个文件的类型可以到网站上通过文件的后缀名搜索得到,或者在Tomcat的conf目录中的web.xml文件中可以找到,如果没找到,就使用"application/octet-stream "即可
那么最后的效果呢


文件成功的被上传上去啦

多文件上传

对于多文件上传相信不用我多说了,就是多次调用addFormDataPart方法添加文件即可

这里把服务器tomcat运行的项目打包一下,给不会写服务器接口的朋友们使用
如果tomcat不会使用的亲们,可以自己查阅一下资料,运行一个已有的项目还是很简单的
把我分享的Test.zip解压缩放到webapps里面,然后启动tomcat就可以了

下面是备用的
访问密码 5d16

总结

从上述okhttp的使用来看,我们发现okhttp对请求封装是非的到位,3.0相比2.0,一些细节的调整更是让这个框架人性化
我从它的一些对象看的出来,面向对象编程这里有着很好的体现,让我用过了就觉得它适合我,我也喜欢用它
当然了,从使用上能看出来,还是有些繁琐的,所以这就需要使用的你去适度的封装,让它变得更简单
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值