• 简介
OkHttp框架近2年是越来越火,当然跟其强大的功能是分不开的;传言在android4.4的源码中Google官方也使用了OkHttp(我没有亲自去核实,所以暂且使用“传言”二字);现在很多公司、甚至第3方很多开源的框架内部都使用的是OkHttp完成的网络请求模块。
其强大的功能可以从2个方面进行说明:

  • 更快:网络请求速度更快,支持HTTP/2技术,提升网络请求速度。当在HTTP/2不可用的情况下,会采用连接池,减少请求延迟,从而提高请求速度。
  • 更省:更省流量,通过GZIP对数据进行压缩并结合缓存机制,从而压缩下载数据的大小、并且在一定的时效内缓存请求的数据,减少短时间内多次请求的流量消耗。
OkHttp除了以上总结的2点之外,还在其他很多方面进行了进行了优化,详情可以查看 官方文档

  • 使用前配置
首先,添加网络请求权限。
  1. <uses-permission android:name="android.permission.INTERNET"/>
复制代码

其次,在Module的build.gradle文件中添加如下代码,完成导包。(注意:写此篇文章时OkHttp的最新版本是3.2.0,在真实使用的时候,请到官网下载最新的包)
  1. compile 'com.squareup.okhttp3:okhttp:3.2.0'
复制代码
  • Get同步请求
  1. //初始化,在一个APP中建议只需要一个OkHttpClient实例,类似Applcation
  2.                 OkHttpClient client = new OkHttpClient();
  3.                 Request request = new Request
  4.                         .Builder() //利用建造者模式创建Request对象
  5.                         .url(Config.URL) //设置请求的URL
  6.                         .build(); //生成Request对象

  7.                 Response response = null;
  8.                 try {
  9.                     //将请求添加到请求队列等待执行,并返回执行后的Response对象
  10.                     response = client.newCall(request).execute();
  11.                     //获取Http Status Code.其中200表示成功
  12.                     if (response.code() == 200) {
  13.                         //这里需要注意,response.body().string()是获取返回的结果,此句话只能调用一次,再次调用获得不到结果。
  14.                         //所以先将结果使用result变量接收
  15.                         String result = response.body().string();
  16.                         Log.d("yangjw",result);
  17.                     }
  18.                 } catch (IOException e) {
  19.                     e.printStackTrace();
  20.                 } finally {
  21.                     if (response != null) {
  22.                         response.body().close();
  23.                     }
  24.                 }
复制代码
以上是OkHttp的Get同步请求。其中请求核心的代码是client.newCall(request).execute();此句代码进行了网络请求,并且没有开新的线程;所以如果此句话是在UI线程中执行,会报错NetworkOnMainThreadException。所有在使用OkHttp的同步请求的时候,需要开启工作线程,将client.newCall(request).execute();放到工作线程中执行。
其中需要注意的问题:
  • response.body().string();一个请求只能获取一次数据,所以如果要对结果进行复用,可以先将结果存放到一个局部变量中,比如文中的result。官方文档有这么一句话:The response body can be consumed only once.翻译:一个response body只能被消耗(使用)一次。
  • response.body().close();请求结束之后,建议将body()关闭。官方文档描述:The response body must be closed. 之所以要关闭body,可以看一下close方法的源码。其中其实是在释放网络资源,关闭网络流。
  • 如果是在new Thread中执行的上述代码,切记要使用Handler将结果返回主线程后进行UI的更新。
同步请求在实际开发中的作用,可以利用OkHttp的同步请求方式,替换android中的HttpUrlConnection进行网络请求。

  • Get异步请求
异步请求,顾名思义就是开启新的线程执行网络请求,异步请求和同步请求在代码上只有一句不同,废话不多说,看下面的代码:
  1. OkHttpClient okHttpClient = new OkHttpClient();
  2.         Request request = new Request.Builder().url(Config.URL).build();
  3.         //enqueue就是将此次的call请求加入异步请求队列,会开启新的线程执行,并将执行的结果通过Callback接口回调的形式返回。
  4.         okHttpClient.newCall(request).enqueue(new Callback() {
  5.             @Override
  6.             public void onFailure(Call call, IOException e) {
  7.                 //请求失败的回调方法
  8.             }

  9.             @Override
  10.             public void onResponse(Call call, Response response) throws IOException {
  11.                 //请求成功的回调方法
  12.                 String result = response.body().string();
  13.                 Log.d("yangjw",result);
  14.                 //关闭body
  15.                 response.body().close();
  16.             }
  17.         });
复制代码
以上就是异步Get请求,和同步请求代码不一样的地方就是enqueue这句okHttpClient.newCall(request).enqueue()。和同步请求不同,异步请求开启了新的线程执行网络请求的代码。也就是说okHttpClient.newCall(request).enqueue()这句是可以在UI线程中直接执行,并且将结果返回到Callback中的onResponse方法中。同样在onResponse方法中通过 response.body().string()获取结果,之后关闭body:response.body().close()。

异步请求的说明:上面我已经提到过,异步请求时开启了一个新的线程执行网络请求,那既然是开启线程就涉及到线程的管理,就要使用到线程池。在OkHttp的异步请求中也是有线程池的,关于这部分的讲解,我会在后面的源码分析中详细的说明。

在开发中可能也有人这样写:new Request.Builder().get().url(Config.URL).build()。可以看到其中多了一个get()方法。此方法的源码如下:
  1. public Builder get() {
  2.       return method("GET", null);
  3.     }
复制代码
也就是设置了一个Get请求的方式。其实不写get()方法,Buidler对象默认就是Get方式,通过Buidler构造器源码一目了然:
  1. public Builder() {
  2.       this.method = "GET";
  3.       this.headers = new Headers.Builder();
  4.     }
复制代码
注意第2行代码,默认设置为GET请求。
所以平时在使用Get方式请求的时候,即使不调用get()方法也是可以的。
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐