学习Okhttp3

1.引言

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

2.正言

okhttp框架的核心类库:

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

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

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<readyAsyncCalls>:缓存(用数组实现,可自动扩容,无大小限制)
    Deque<runningAsyncCalls>:正在运行的任务,仅仅是用来引用正在运行的任务以判断并发量,注意它并不是消费者缓存

根据生产者消费者模型的模型理论,当入队(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()函数,手动移动缓存区(可以看出这里是主动清理的,因此不会发生死锁)

okhttp dispatcher

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

image.png

进一步追踪ConnectInterceptor 发现:

image.png

StreamAllocation类:

image.png

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

image.png

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

image.png

RealInterceptorChain:

总体请求过程

image.png

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

image.png

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

image.png

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 参考资源 官网 国内博客 GitHub官网 鉴于一些关于OKHttp3源码的解析文档过于碎片化,本文系统的,由浅入...
    风骨依存阅读 12,497评论 11 82
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,646评论 18 139
  • 前言 做React Native的时候遇到业务线反馈的一个Bug:在使用Charles做代理的时候,将reactT...
    灵丞阅读 12,740评论 2 36
  • 背书背到崩溃,画个画缓解一下,结果画到了凌晨。
    则鱼阅读 345评论 6 8
  • 停电了,周围很黑,想给你发一个我剪完头发后的俊美照片也没有光亮了。就是最近感觉有好多话要给你说,想和你面对面的聊天...
    SZhua阅读 152评论 0 0