利器OkHttp的使用以及简单封装

前言

Android开发中网络编程是必不可少的,不接入互联网的APP就没有盈利可言。废话不多说了,下面请先看Android中网络请求的进化图:

 

HttpURLConnection,Apache HTTP Client,Volley到现在的OKHttp,可谓天外有天,人外有人。为什么OKHttp会这么火呢,相信下面的介绍会告诉你答案。

OKHttp的简介

首先,给出OKHttp的项目地址:https://github.com/square/okhttp

Android为我们提供了两种HTTP交互的方式: HttpURLConnection 和 Apache HTTP Client,虽然两者都支持HTTPS,流的上传和下载,配置超时,IPv6和连接池,已足够满足我们各种HTTP请求的需求。但更高效的使用HTTP可以让您的应用运行更快、更节省流量。而OkHttp库就是为此而生。 OkHttp是一个高效的HTTP库:

1.支持 SPDY ,共享同一个Socket来处理同一个服务器的所有请求

2.如果SPDY不可用,则通过连接池来减少请求延时

3.无缝的支持GZIP来减少数据流量

1.缓存响应数据来减少重复的网络请求

2.一般的get请求

3.一般的post请求

4.基于Http的文件上传

5.文件下载

6.加载图片

7.支持请求回调,直接返回对象、对象集合

8.支持session的保持

OkHttp会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当***个IP连接失败的时候,会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。(并发) 使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。如果您用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。 从上面的简单介绍中可以知道,虽然在编程上面并不会简洁很多,但是OKHttp内部的一些功能能够帮助我们自动完成一些很复杂的操作,笔者个人认为***的卖点就是大大节省用户的流量。

OKHttp的基本使用

1、在Gradle中引入CardView的依赖库。

 
 
 
 
  1. compile 'com.squareup.okhttp:okhttp:3.8.0' 

2、OKHttp在使用之前,首先要了解下面几个比较核心的类以及它的功能。

  • OkHttpClient 客户端对象
  • Request是OkHttp中访问的请求,Post请求中需要包含RequestBody
  • Builder是辅助类,用于生产对象
  • Response即OkHttp中的响应,响应中可以得到返回是否成功,返回数据
  • MediaType 数据类型,用来表明是JSON等一系列格式
  • RequestBody 请求数据,在Post请求中用到
  • client.newCall(request).execute()是同步的请求方法
  • client.newCall(request).enqueue(Callback callBack)是异步的请求方法,但是Callback里面的代码是执行在子线程的,因此不能更新UI。

3、OKHttp的基本使用步骤(以POST方式从服务器取JSON数据为例)

  • 创建OkHttpClient对象,官方文档要求我们***使用单例模式,在后文对OKHttp进行封装的时候会提到。
  • 如果是post请求的话,需要通过FormEncodingBuilder创建RequestBody对象,指定需要post传进去的参数。get请求则不用。
  • 创建Request对象,这个对象是请求对象,需要指定URL。post请求的时候需要指定RequestBody对象,get请求则不用。
  • 调用OkHttpClient的newCall方法,把Request对象传进去,然后执行execute或者enqueue方法,两者的区别在上文已提到。在CallBack中的onResponse方法就可以做你需要做的事。onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()看到这,你可能会奇怪,竟然还能拿到返回的inputStream,看到这个最起码能意识到一点,这里支持大文件下载,有inputStream我们就可以通过IO的方式写文件。不过也说明一个问题,这个onResponse执行的线程并不是UI线程。的确是的,如果你希望操作控件,还是需要使用handler等。
 
 
 
 
  1. OkHttpClient client = new OkHttpClient(); 
  2.  
  3.     RequestBody body = new FormEncodingBuilder() 
  4.             .add("type""1"
  5.             .build();    Request request = new Request.Builder() 
  6.             .url(Constants.URL_BANNER) 
  7.             .post(body) 
  8.             .build(); 
  9.  
  10.     client.newCall(request).enqueue(new Callback() { 
  11.         @Override         
  12.     public void onFailure(Request request, IOException e) { 
  13.  
  14.         } 
  15.  
  16.         @Override         
  17.     public void onResponse(Response response) throws IOException {             
  18.             if (response.isSuccessful()) { 
  19.  
  20.                 android.os.Message msg = new Message(); 
  21.                 msg.what = 1; 
  22.                 msg.obj = response.body().string(); 
  23.                 mHandler.sendMessage(msg); 
  24.             } 
  25.         } 
  26.     });  

这里只是一个简单post请求,从服务器获取数据的介绍,至于get请求只不过是去掉RequestBody对象而已。至于如何向服务器提交数据,可以在熟悉上面的基本用法之后查阅官方的WIKI(GitHub的介绍文档)。

OKHttp的简单封装

回顾上面的代码,试想一下如果每次请求都写这么多重复代码,这样会严重降低开发效率,因此需要对OKHttp进行封装。对代码进行封装是我们最为面向对象程序员的基本素养,减少重复代码,降低维护难度以及成本。

GitHub上也有对OKHttp进行过封装,叫做OKHttpUtils。不过这里我们自己动手,一起来学习一下如何进行封装。具体的注意点有下面几点:

1、首先,OKHttp官方要求我们***用单例模式去使用OKHttpClient类的,因此我们自定义一个OKHttpHelper类,并且使用单例模式。

2、对get以及post方法进行封装,主要的思想是把共同的代码抽取出来,例如代码中被抽取出来的request方法。

3、对外公开一些静态方法,包括get和post方法等。

4、Callback基类,对OKHttp的回调进行封装。这个类用里面有一个type,是方便回调中使用Gson对JSON进行解析的封装。使用Callback的时候只需要在泛型中传入类似Data 、List<Data>即可以方便地使用JSON。

5、由于原来的回调不在主线程,因此我们需要使用Handler来将回调放入主线程。

其余的可以参照代码,有详细注释。

  1. /** 
  2.  * 这个类用来辅助OKHttp 
  3.  */public class OkHttpHelper {    /** 
  4.      * 采用单例模式使用OkHttpClient 
  5.      */ 
  6.     private static OkHttpHelper mOkHttpHelperInstance;     
  7.     private static OkHttpClient mClientInstance;     
  8.     private Handler mHandler;     
  9.     private Gson mGson;    /** 
  10.      * 单例模式,私有构造函数,构造函数里面进行一些初始化 
  11.      */ 
  12.     private OkHttpHelper() { 
  13.         mClientInstance = new OkHttpClient(); 
  14.  
  15.         mClientInstance.setConnectTimeout(10, TimeUnit.SECONDS); 
  16.         mClientInstance.setReadTimeout(10, TimeUnit.SECONDS); 
  17.         mClientInstance.setWriteTimeout(30, TimeUnit.SECONDS); 
  18.         mGson = new Gson(); 
  19.  
  20.         mHandler = new Handler(Looper.getMainLooper()); 
  21.     }    /** 
  22.      * 获取实例 
  23.      * 
  24.      * @return 
  25.      */ 
  26.     public static OkHttpHelper getinstance() {         
  27.         if (mOkHttpHelperInstance == null) {             
  28.             synchronized (OkHttpHelper.class) {                 
  29.                 if (mOkHttpHelperInstance == null) { 
  30.                     mOkHttpHelperInstance = new OkHttpHelper(); 
  31.                 } 
  32.             } 
  33.         }        return mOkHttpHelperInstance; 
  34.     }    /** 
  35.      * 封装一个request方法,不管post或者get方法中都会用到 
  36.      */ 
  37.     public void request(final Request request, final BaseCallback callback) {        //在请求之前所做的事,比如弹出对话框等 
  38.         callback.onRequestBefore(); 
  39.  
  40.         mClientInstance.newCall(request).enqueue(new Callback() {             
  41.             @Override 
  42.             public void onFailure(Request request, IOException e) {                //返回失败 
  43.                 callbackFailure(request, callback, e); 
  44.             }            @Override 
  45.             public void onResponse(Response response) throws IOException { &nbs
THE END