1、OkHttp介绍
OkHttp是Square公司开发的Http通用库,支持HTTP和HTTPP/2,用于Android和Java应用开发。OkHttp是一款高效的HTTP客户端,支持同一个地址的链接共享同一个socket,通过连接池来减小响应延迟,还有透明的GZIP压缩,请求缓存等优势。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。
HttpURLConnection 是一个多用途、轻量级的http客户端,它对网络请求的封装没有HttpClient彻底,api比较简单,用起来没有那么方便。虽然易于扩展但是封装起来相对困难,在Android2.2中存在关闭Inputstream 时连接池失效等问题,通常需要禁用连接池来解决。Android4.4原生的HttpURLConnection底层已经替换成了OkHttp实现
HttpClient时Apache的一个三方网络框架,网络请求做了完善的封装,api众多,用起来比较方便,开发快。使用比较稳定,但是正是由于其api众多,使得很难在不破坏兼容性的情况下对其进行扩展。所以android5.0中被废弃,6.0逐渐删除,全面转向使用OkHttp.
目前有很多知名的Android三方框架都使用OKHttp作为网络连接的默认基栈,例如Volley,Gilde,Retrofit等。
2、基本使用
(1)、在项目中添加对OkHttp的依赖。
在需要使用OkHttp的模块的build。gradle文件中,添加如下依赖库。(版本号可能存在变更)
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.6.0'
}
(2)、初始化
OkHttp框架的核心类是OkHttpClient,此类可直接实例化。由于OkHttpClient 内部处理了并发,多线程和Socket重用等问题,为了节省资源,整个应用中使用一个OkHttpClient对象即可,可以对它做Singleton(单例)封装。
OkHttpClient client=new OkHttpClient();
(3)、OkHttp请求构建
代表Http请求的类是Request,该类使用构造器模式,最简单的构造get(默认是get请求体)请求如下。
Request request=new Request.Builder()
.url("url")
.build();
构造post请求,在构建Request时添加请求体 RequestBody示例如下:
RequestBody body=new FormBody.Builder()
.add("name","张飞")
.add("age","12")
.build();
Request request=new Request.Builder() .post(body) .url(url) .build();
(4)、OkHttp请求的发送
请求的发送有两种形式:一种是直接同步执行,阻塞调用线程,直接返回结果;(不推荐,Android中可能阻塞UI线程)
另一种是通过队列异步执行,不阻塞调用线程,通过回调方法返回结果。如下所示:
同步执行:
//如果返回null,代表超时或没有网络连接
Response response=client.newCall(request).execute();
异步回调:
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//超时或没有网络连接
//注意:这里是后台线程!(更新UI需要切换到UI线程)
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//成功
//注意:这里是后台线程!(更新UI需要切换到UI 线程)
}
});
以上简单介绍OkHttp使用,最后会附上源码
3、OkHttp详解
Request、Response、Call 基本概念
上面的代码中涉及到几个常用的类:Request、Response和Call。下面分别介绍:
Request
每一个HTTP请求包含一个URL、一个方法(GET或POST或其他)、一些HTTP头。请求还可能包含一个特定内容类型的数据类的主体部分。
Response
响应是对请求的回复,包含状态码、HTTP头和主体部分。
Call 模型
OkHttp使用Call抽象出一个满足请求的模型,尽管中间可能会有多个请求或响应。执行Call有两种方式,同步或异
Http客户端的任务是处理请求和响应,这说起来简单,但实际过程很复杂。
请求:Http请求包含URL,请求方法(例如GET或者POST),请求头。还可能包含请求体,可以是数据流也可以是指定的内容类别。
响应:用一个响应码来回应请求(例如200代表成功,404代表页面未找到),响应头和响应体。
请求的重写
为了保证正确性和传输效率,OkHttp会在发送你的请求之前重写它,例如:如下
OkHttp可能会添加原始请求中缺失的头部信息,包括Content-Length【内容长度】、Transfer-Encoding(传输编码),User-Agent(用户代理) ,Host (主机), Connecton(连接)和 Content-Type(内容类型)。
为了实现透明的响应压缩(transparent response compression),OkHttp会增加Accept-Encoding头信息。
如果你收到了cookie,OkHttp会增加Cookie 头信息。
某些请求可能会对响应做缓存。如果被缓存的响应不是最新的,OkHttp能做一个有条件的GET请求来下载更新后的响应。此功能需要添加 If - Modified -Since和 If -Node-Match等头信息。
响应的重写
如果使用了透明压缩,OkHttp 会去掉对响应Content -Encoding 和 Content - Length头信息,因为他们不能应用于解压后的响应体。
如果有条件的GET成功了,网络侧的响应和缓存的响应会被自动合并。
重定向
如果你请求的URL被移动了,服务器会返回类似于302这样的响应码,来指明新的URL。OkHttp能跟随新的URL,获取到最终的响应。(用户只需发送一次Okhttp请求,由OkHttp 负责完成重定向请求,并获得最终请求结果)
请求的重试
有时会发生连接失败:可能网络连接状况不好,或者服务器不可达。OkHttp会自动使用不同的路由来重试请求。
Call模型
由于以上的重写,重定向和重试等操作,你的一个简单请求可能会产生多个请求和响应。OkHttp使用Call这个概念对此来建模:不论为了满足你的请求任务,中间做了多少次请求和响应,都算作一个Call。
Call有两种方式来执行:
同步方式:你的线程会被阻塞,直到响应可读。
异步方式:你在任意线程将请求排队,当响应可读时,会在另一个线程拿到回调。
Call的取消
使用Call.cancel()来停止一个执行中的请求。如果线程正在请求或读取响应,则会收到IOException。使用此方法,在一个Call已经不需要时取消它,可以节省网络流量。
Call可以在任意线程取消,如果请求没有完成,调用取消方法会导致请求失败,读写请求体和响应体的代码会产生IOException。
拦截器
OkHtttp在请求响应过程中可以添加拦截器,拦截器和响应的数据等。
需要添加依赖
//日志拦截器
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
用法
//初始化日志拦截器
HttpLoggingInterceptor interceptor=new HttpLoggingInterceptor();
//设置拦截级别 (NONE:没有日志; BASIC:基本 HEADERS ;BODY )
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
//添加拦截器
OkHttpClient client=new OkHttpClient().newBuilder().addInterceptor(interceptor).build();