学习Okhttp3

1.引言

面试的时候经常被问及到okhttp3 ,retrofit2实现原理。而自己也只是停留在使用的层次对于内部的机制也是不懂。趁着10.1放假。学习下okhttp3.做下笔记。。参考文献http://frodoking.github.io/2015/03/12/android-okhttp/, http://www.jianshu.com/p/aad5aacd79bf

2.正言

okhttp框架的核心类库:

OkHttpClient:
配置和创建http连接。大多数应用程序可以使用一个单一的okhttpclient他们所有的HTTP请求-受益于一个共享的响应缓存、线程池、连接复用,等。
实例okhttpclient拟完全配置在他们共享曾经分享他们应该被视为一成不变的,可以安全地用于同时打开新的连接。如果需要,线程可以调用克隆做的okhttpclient可以安全地修改与进一步的配置变化浅拷贝。

Request:(构造者模式)
封装的一个Http请求。

学习Okhttp3_第1张图片
image.png

RequestBody:
RequestBody类是请求体类,上传数据的封装,它的writeTo方法可以得到流对象,然后将请求体数据写到服务器。这是上传数据的核心方法

1,public abstract MediaType contentType()//数据类型
2,public long contentLength()//数据长度
3,public abstract void writeTo(BufferedSink sink)//写操作

BufferedSink 类是square公司开源的IO框架Okio中的一个类,这个类封装了OutputStream,即本质是一个输出流,具有write方法。Okio框架和BufferedSink 类也不是本篇介绍的重点,这儿不做讲解。把BufferedSink 当成OutputStream使用即可。
RequestBody的子类有 FormBody,MultipartBody。根据不同的上传数据类型选择不同的body。

InternalCache :存储Response信息的类
//下面一行很重要,这个方法会去获取client中的Cache。同时Cache在初始化的时候会去读取缓存目录中关于曾经请求过的所有信息。
InternalCache responseCache = Internal.instance.internalCache(client);
Response cacheCandidate = responseCache != null? responseCache.get(request): null;

Dispatcher:
当异步请求执行的政策。每个dispatcher里面通过ExecutorService 来执行Call。

  1. Dispatcher的结构
    Dispatcher维护了如下变量,用于控制并发的请求
    maxRequests = 64: 最大并发请求数为64
    maxRequestsPerHost = 5: 每个主机最大请求数为5
    Dispatcher: 分发者,也就是生产者(默认在主线程)
    AsyncCall: 队列中需要处理的Runnable(包装了异步回调接口)
    ExecutorService:消费者池(也就是线程池)
    Deque:缓存(用数组实现,可自动扩容,无大小限制)
    Deque:正在运行的任务,仅仅是用来引用正在运行的任务以判断并发量,注意它并不是消费者缓存

根据生产者消费者模型的模型理论,当入队(enqueue)请求时,如果满足(runningRequests<64 && runningRequestsPerHost<5),那么就直接把AsyncCall直接加到runningCalls的队列中,并在线程池中执行。如果消费者缓存满了,就放入readyAsyncCalls进行缓存等待。当任务执行完成后,调用[finished(https://github.com/square/okhttp/blob/7826bcb2fb1facb697a4c512776756c05d8c9deb/okhttp/rc/main/java/okhttp3/Dispatcher.java#L142-L142)的promoteCalls()函数,手动移动缓存区(可以看出这里是主动清理的,因此不会发生死锁)

学习Okhttp3_第2张图片
okhttp dispatcher

RealCall:
Dispatcher中executorService().execute(call),是执行一个请求。追踪代码发现。这代码的本质上是调用了。RealCall类中的getResponseWithInterceptorChain得到Response 返回对象。。

学习Okhttp3_第3张图片
image.png

进一步追踪ConnectInterceptor 发现:

学习Okhttp3_第4张图片
image.png

StreamAllocation类:

学习Okhttp3_第5张图片
image.png

StreamAllocation 里面主要是得到RealConnection对象。。跟踪RealConnection对象。发现RealConnection 有raw socket的操作:

学习Okhttp3_第6张图片
image.png

Interceptor:
这个接口很重要,一般都是调用Interceptor.interceptor(Chain chain )。这方法实际上执行的是 chain.proceed(Request request)。 okhttp3 里面得到Response,实际上就是通过chain.proceed() 方法得到的。

学习Okhttp3_第7张图片
image.png

RealInterceptorChain:

总体请求过程

学习Okhttp3_第8张图片
image.png

上面是OKHttp总体设计图,主要是通过Diapatcher不断从RequestQueue中取出请求(Call),根据是否已缓存调用Cache或Network这两类数据获取接口之一,从内存缓存或是服务器取得请求的数据。该引擎有同步和异步请求,同步请求通过Call.execute()直接返回当前的Response,而异步请求会把当前的请求Call.enqueue添加(AsyncCall)到请求队列中,并通过回调(Callback)的方式来获取最后结果。

学习Okhttp3_第9张图片
image.png

详细类关系图
由于整个设计类图比较大,所以本人将从核心入口client、cache、interceptor、网络配置、连接池、平台适配性…这些方面来逐一进行分析源代码的设计。
下面是核心入口OkHttpClient的类设计图

学习Okhttp3_第10张图片
image.png

从OkHttpClient类的整体设计来看,它采用门面模式来。client知晓子模块的所有配置以及提供需要的参数。client会将所有从客户端发来的请求委派到相应的子系统去。
在该系统中,有多个子系统、类或者类的集合。例如上面的cache、连接以及连接池相关类的集合、网络配置相关类集合等等。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。同时,OkHttpClient可以看作是整个框架的上下文。
通过类图,其实很明显反应了该框架的几大核心子系统;路由、连接协议、拦截器、代理、安全性认证、连接池以及网络适配。从client大大降低了开发者使用难度。同时非常明了的展示了该框架在所有需要的配置以及获取结果的方式。
在接下来的几个Section中将会结合子模块核心类的设计,从该框架的整体特性上来分析这些模块是如何实现各自功能。以及各个模块之间是如何相互配合来完成客户端各种复杂请求。

你可能感兴趣的:(学习Okhttp3)