优秀的网络请求框架OKhttp---初识篇
在讲OKhttp之前我们先说一下http的的出现及发展
HTTP协议结构
http的组成是请求头,请求体,响应头,响应体。
请求头:本次请求的客户端;本次请求所使用的cookie;本次请求需要返回的数据类型;本次请求是否采用数据压缩等等设置。
请求体:指定本次请求所使用的方法是get/post;主要用来携带本次请求的参数。
响应头:服务器的标识;状态码200/300/404/500等;内容编码;服务器返回给客户端的cookie。
响应体:就是我们本次请求所返回的数据
HTTP协议工作的一个流程
1、首先客户机与服务器需要建立连接
2、建立连接后,客户机发送一个请求给服务器
3、服务器接到请求后,给予相应的响应信息
4、客户端接收服务器所返回的信息,连接断开
HTTP协议的优势
简单快速;灵活;无连接;无状态
SPDY介绍
SPDY是兼容性协议
多路复用请求
对请求划分优先级
压缩请求头
HTTP2.0是基于SPDY,IETF定制的新一代HTTP协议
更安全的SSL
终于来到了我们的重点OKhttp,为我们android客户端支持HTTP2.0提供了途径。
那么OKhttp有哪些优势呢?
1)OKhttp如果支持SPDY,HTTP2.0共享同一个socket来处理同一个服务器的所有请求
2)如果SPDY不可用,则通过连接池来减少请求延时
3)无缝的支持GZIP来减少数据流量
4)缓存响应数据来减少重复的网络数据
5)可以从很多常用的连接问题中自动恢复。
接下来我们看一张OKhttp框架的基本原理图
对这张图片讲解,请求request----》到达了分发器-----》分发器就会传递到HttpEngine,这个HttpEngine就是真正干活的人,他会看这次缓存有没有缓存,如果有从缓存里面拿到信息,如果没有它就会到连接池中,从连接池中创建一个connnection连接,通过connnection发我们真正的请求,请求到以后通过路由和Platform找到一个合适的平台,这时候通过Server、socket获得Data。
下面这张是执行流程图:
大概流程是这样的: 1.用构造者模式去创建一个请求(Request) okhttp普遍使用构建者模式开发 Request.Builder 2.添加到分发器中(Dispatcher) 3.由分发器分发到httpEngine,如果这个请求在之前有缓存过,那么直接返回缓存的Response,否者创建连接。 (HttpEngine首先调用nextConnection(),获取不到Connection 才会调用createNextConnection()) 4.从连接池中获得一个连接,进行网络请求(...)OKhttp支持各种版本的协议并且具有下面两种特性。
多路复用机制:HttpEngine(Http引擎)每次请求数据时,都会先调用nextConnection(),如果返回一个连接对象,则就调用sendRequest()发送一个请求。如果nextConnection()返回为null,就会调用createNextConnection()创建一个连接,然后去发送请求。 重连机制:通过一个while的循环,判断条件是当前状态是否连接,如果没有连接,就会调用getResquese()发送请求,紧接着HttpEngine调用recover(),进行重连操作,直到当前连接状态为已连接,结束循环。
OKhttp源码解析: 首先看一下Route类,路由类,它主要是封装了Address,所有要请求的端口号,服务器的ip地址等等。最后在建立connnection的时候,从我们的Route类中获取相对应的数据;ResponseBody响应体类,返回的所有数据最初都是字节码。操作的就是这个字节数组,把它转化成String类型或者图片类型,每一个call都是我们最终要实行的一个接口;分发器类,里面有一个线程池,包括两种异步的,一种同步的方法;HttpEngine是真正的发送请求的,他是核心类,真正的发送请求,响应处理,重连机制等,核心方法SendRequest()各个类之间的配合通过OKhttpClient。 简单的介绍了一些OKhttp的源码类,我们通过实际代码进行一些简单的演示 通过OKhttp进行get请求: /** * 需要注意的是此时还在费UI线程中要想更新UI需要使用handler或者runOnUiThread */ //发送一个get请求 public void getRequest() { //构建请求体 final Request request = new Request.Builder().url("https://hao.360.cn/").build(); OkHttpClient client = new OkHttpClient(); //通过request构造了一个任务类call Call call = client.newCall(request); //把call调度起来,call的回调方法来响应我们的请求 call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { } @Override public void onResponse(Response response) throws IOException { final String a = response.body().toString(); runOnUiThread(new Runnable() { @Override public void run() { //可以在这里面更新ui } }); } }); }通过OKhttp进行post请求:
/**
* 发送一个post请求
*/
public void postRequest() {
OkHttpClient client = new OkHttpClient();
FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
formEncodingBuilder.add("mb", "15941630147");
formEncodingBuilder.add("pwd", "12321312");
Request request = new Request.Builder().url("https://hao.360.cn/").post(formEncodingBuilder.build()).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
//这也是在非UI线程中的
@Override
public void onResponse(Response response) throws IOException {
}
});
}
}
通过代码和以上的讲解,读者应该对OKhttp网络请求框架有了一定的了解,但是从上面的代码中可以看出很多代码还是重复出现的为了优化代码,防止冗余现象的出现,对OKhttp还要进行一次封装,下一篇我将会讲解对Okhttp请求的进一步封装。