OkHttp3源码详解(二) 整体流程
1.简单使用
同步:
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain(false);
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
首先加锁置标志位,接着使用分配器的executed方法将call加入到同步队列中,然后调用getResponseWithInterceptorChain方法(稍后分析)执行http请求,最后调用finishied方法将call从同步队列中删除
异步:
void enqueue(Callback responseCallback, boolean forWebSocket) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));
}
同样先置标志位,然后将封装的一个执行体放到异步执行队列中。这里面引入了一个新的类AsyncCall,这个类继承于NamedRunnable,实现了Runnable接口。NamedRunnable可以给当前的线程设置名字,并且用模板方法将线程的执行体放到了execute方法中
2.总体架构
上图是OkHttp的总体架构,大致可以分为以下几层:
- Interface——接口层:接受网络访问请求
- Protocol——协议层:处理协议逻辑
- Connection——连接层:管理网络连接,发送新的请求,接收服务器访问
- Cache——缓存层:管理本地缓存
- I/O——I/O层:实际数据读写实现
- Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑
①Interface——接口层:
接口层接收用户的网络访问请求(同步请求/异步请求),发起实际的网络访问。OkHttpClient
是OkHttp框架的客户端,更确切的说是一个用户面板。用户使用OkHttp进行各种设置,发起各种网络请求都是通过OkHttpClient
完成的。每个OkHttpClient
内部都维护了属于自己的任务队列,连接池,Cache,拦截器等,所以在使用OkHttp作为网络框架时应该全局共享一个OkHttpClient
实例。
Call
描述一个实际的访问请求,用户的每一个网络请求都是一个Call
实例。Call
本身只是一个接口,定义了Call
的接口方法,实际执行过程中,OkHttp会为每一个请求创建一个RealCall
,每一个RealCall
内部有一个AsyncCall
,AsyncCall
继承的NamedRunnable
继承自Runnable接口。
所以每一个Call就是一个线程,而执行Call的过程就是执行其execute
方法的过程。
Dispatcher
是OkHttp的任务队列,其内部维护了一个线程池,当有接收到一个Call
时,Dispatcher
负责在线程池中找到空闲的线程并执行其execute
方法。这部分将会单独拿一篇博客进行介绍,详细内容可参考本系列接下来的文章。
②.Protocol——协议层:处理协议逻辑
Protocol层负责处理协议逻辑,OkHttp支持Http1/Http2/WebSocket协议,并在3.7版本中放弃了对Spdy协议,鼓励开发者使用Http/2。
③.Connection——连接层:管理网络连接,发送新的请求,接收服务器访问
连接层顾名思义就是负责网络连接。在连接层中有一个连接池,统一管理所有的Socket连接,当用户新发起一个网络请求时,OkHttp会首先从连接池中查找是否有符合要求的连接,如果有则直接通过该连接发送网络请求;否则新创建一个网络连接。
RealConnection
描述一个物理Socket连接,连接池中维护多个RealConnection实例。由于Http/2支持多路复用,一个RealConnection
可以支持多个网络访问请求,所以OkHttp又引入了StreamAllocation
来描述一个实际的网络请求开销(从逻辑上一个Stream
对应一个Call
,但在实际网络请求过程中一个Call
常常涉及到多次请求。如重定向,Authenticate等场景。所以准确地说,一个Stream
对应一次请求,而一个Call
对应一组有逻辑关联的Stream
),一个RealConnection
对应一个或多个StreamAllocation
,所以StreamAllocation
可以看做是RealConenction
的计数器,当RealConnection
的引用计数变为0,且长时间没有被其他请求重新占用就将被释放。
连接层是OkHttp的核心部分,这部分当然也会单独拿一篇博客详细讲解,详细内容可参考本专题相关文章。
④.Cache——缓存层:管理本地缓存
Cache层负责维护请求缓存,当用户的网络请求在本地已有符合要求的缓存时,OkHttp会直接从缓存中返回结果,从而节省网络开销。这部分内容也会单独拿一篇博客进行介绍,详细内容可参考本专题相关文章。
⑤.I/O——I/O层:实际数据读写实现
I/O层负责实际的数据读写。OkHttp的另一大有点就是其高效的I/O操作,这归因于其高效的I/O库okio
这部分内容笔者也打算另开一个专题进行介绍。详细内容可以参考本博客相关内容。
⑥Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑
拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。
OkHttp3源码详解(二) 整体流程的更多相关文章
- OkHttp3源码详解(一) Request类
每一次网络请求都是一个Request,Request是对url,method,header,body的封装,也是对Http协议中请求行,请求头,实体内容的封装 public final class R ...
- OkHttp3源码详解(三) 拦截器-RetryAndFollowUpInterceptor
最大恢复追逐次数: ; 处理的业务: 实例化StreamAllocation,初始化一个Socket连接对象,获取到输入/输出流()基于Okio 开启循环,执行下一个调用链(拦截器),等待返回结果(R ...
- OkHttp3源码详解(五) okhttp连接池复用机制
1.概述 提高网络性能优化,很重要的一点就是降低延迟和提升响应速度. 通常我们在浏览器中发起请求的时候header部分往往是这样的 keep-alive 就是浏览器和服务端之间保持长连接,这个连接是可 ...
- OkHttp3源码详解(三) 拦截器
1.构造Demo 首先构造一个简单的异步网络访问Demo: OkHttpClient client = new OkHttpClient(); Request request = new Reques ...
- OkHttp3源码详解(六) Okhttp任务队列工作原理
1 概述 1.1 引言 android完成非阻塞式的异步请求的时候都是通过启动子线程的方式来解决,子线程执行完任务的之后通过handler的方式来和主线程来完成通信.无限制的创建线程,会给系统带来大量 ...
- vue 源码详解(二): 组件生命周期初始化、事件系统初始化
vue 源码详解(二): 组件生命周期初始化.事件系统初始化 上一篇文章 生成 Vue 实例前的准备工作 讲解了实例化前的准备工作, 接下来我们继续看, 我们调用 new Vue() 的时候, 其内部 ...
- spring事务详解(三)源码详解
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- Shiro 登录认证源码详解
Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...
- Activiti架构分析及源码详解
目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...
随机推荐
- Python系列之环境安装
Python可以实现强大的数据爬虫功能,并且数据分析与挖掘挺方便,也提供了大量的库,比如numpy, pands,matplotlib等.尤其,使用Python做机器学习也成了近年来的趋势,有人经常会 ...
- [视频]K8飞刀 HackIE\EXP测试\Post提交
[视频]K8飞刀 HackIE VS Firefox Hackbar插件功能对比 视频中可看到HackBar有缺陷导致Payload无法执行 链接:https://pan.baidu.com/s/15 ...
- sql 指定时间 所在的周、月、季、年
DECLARE @TodayDateTime DATETIMEDECLARE @strToday NVARCHAR(19) DECLARE @TodayBeginDateTime DATETIMEDE ...
- 通过Anaconda在Ubuntu16.04上安装 TensorFlow(GPU版本)
一. 安装环境 Ubuntu16.04.3 LST GPU: GeForce GTX1070 Python: 3.5 CUDA Toolkit 8.0 GA1 (Sept 2016) cuDNN v6 ...
- LintCode翻转字符串问题 - python实现
题目描述:试实现一个函数reverseWords,该函数传入参数是一个字符串,返回值是单词间做逆序调整后的字符串(只做单词顺序的调整即可). 例如:传入参数为"the sky is blue ...
- Hive的union和join操作
建表语句: create table tb_in_base ( id bigint, devid bigint, devname string ) partitioned b ...
- WebView使用_WebView监听网页下载_DownloadManager使用
最近在做一个较简单的项目:通过一个webview来显示一个网页的App 这个网页有下载的功能,关于这一功能需要用到两个知识点: 1.webview监听网页的下载链接.(webview默认情况下是没有开 ...
- 从零开始学 Web 之 JavaScript(三)函数
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...
- kubernetes1.13之后的kubeadm init config
1.kubernetes1.13之后kubeadm开始GA,由于1.13的kube-proxy有bug,删除ipvs的地方总是导致kube-proxy挂掉,所以建议直接用1.13.2,这个版本解决了b ...
- OpenCV Mat与UIImage之间的转换
UIImage 转 OpenCV cvMat: - (cv::Mat)cvMatWithImage:(UIImage *)image { CGColorSpaceRef colorSpace = CG ...