文章思维导图
前言
进行 okhttp
的核心源码分析,必须要搞清楚 http 协议以及相关的网络协议。这里只对协议容易混淆的地方进行说明。
首先我们要明确一点,要想让两台计算机进行通信,首先需要建立连接,也就是我们常说的三次握手。
计算机A 要想和计算机 B 进行通信,首先要知道计算机B 的IP 地址,知道 IP 地址后,就能访问计算机B,而要和计算机B上的那个程序通信,这个时候就需要 TCP 的地址了,也就是端口号。有了这两个信息,两者就可以建立连接了。其实这个时候就可以进行通信了。体现在代码中,就是通过 Socket
建立连接,然后进行读写操作。
这个时候也看出来了,所谓的 Socket
其实就是对 TCP/IP 建立连接通信的一种具体封装,不同的语言代码有不同的实现。有了 Socket
后,开发者就可以方便地进行网络连接通信了。Socket 本身并不是 TCP/IP网络协议中的协议
HTTP
协议就是在建立了 Socket
连接后规定了通信内容的格式,大家都遵从这个协议进行通信。
HTTP通信内容?
简单来说,所谓的 HTTP 通信就是建立 Socket 连接,然后把通信内容拼接成符合 HTTP 报文的内容发送出去。
什么是 okhttp
有了前言的内容,我们就可以理解什么是 okhttp
了,所谓的 okhttp
就是通过代码的方式实现了各种协议,将这些通信协议封装起来,让我们可以快速地用代码来实现。
okhttp 好处
- 支持 HTTP1、HTTP2、Quic以及 WebSocket
之所以支持,是因为okhttp
的源码里面对这些协议的规则进行了实现。 - 连接池复用底层 TCP连接,减少请求延时。
建立 TCP 连接是需要时间的,okHTTP 源码中对已经连接的 TCP,其实在代码中的体现就是Socket
进行了缓存,再次请求同一地址的时候就不用重复建立连接了,从而减少请求延时。 - 无缝的支持 GZIP 减少数据流量
其实这是 HTTP 协议的内容,HTTP 协议中可以在请求头中规定是否支持数据压缩,okhttp 就把这个请求头封装进去了,告诉服务器,我可以接受一个 GZIP 压缩的数据报文。 - 缓存响应数据减少重复的网络请求
这也是 HTTP 协议中定义的内容,有对应的字段表示 - 请求失败自动重试主机的其他 ip,自动重定向
同样也是 HTTP 协议中定义的内容。
可见所谓的这些好处,其实就是 okhttp
利用 HTTP 报文格式中规定的内容,然后进行处理,完成这些规定。如果没有处理的话,任凭服务器发送来的报文是什么,如果统统不管的话,那也是没用的。
因此再次说明 HTTP 协议只是规定了你我通信要发送的内容需要遵从什么样的格式,至于我有没有根据内容,实现对应的功能,那就不是 HTTP 协议的范围了。
okhttp 使用
// 步骤 1
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(60,TimeUnit.SECONDS)
.connectTimeout(60,TimeUnit.SECONDS)
.cache(new Cache(new File("xx"),1024))
.build();
// 步骤 2
Request request = new Request.Builder()
.url(AppConfig.URL.url_get)
.build();
// 步骤 3
Call call = okHttpClient.newCall(request);
// 步骤 4
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
okhttp
的使用一般就是上面 4 步。
第一步:创建 okhttpClient
,也就是一个客户端,同时也是也 Call 的工厂,主要作用就是记录一些配置内容,比如 :连接超时时间、读取超时时间、缓存地址等等这种配置。这个对象可以共用,不用每次都创建。
第二步:就是创建一个请求报文。
第三步:就是通过 Call 工厂 okhttpClient
和 请求报文,构建出一个准备好要执行的请求。通过 Call 来发起网络请求。
第四步:发起网络请求
虽然就这样简单的四步,但是代码设计的非常好,首先做到了功能分离!单一职责,有三个类 OkhttpClient
、Request
、Call
分别负责不同的职责,非常清晰。
核心原理分析
okhttp 整个大的流程核心就是一个分发器 Dispatcher
和 拦截器 interceptors
下面分别分析
Dispatcher
分发器用于执行我们网络请求的异步任务,Dispatcher
有 4 个核心成员对象 :
- ExecutorService
线程池,用于执行异步任务 - 三个队列
Deque
三个队列,分别是用于存储 正在执行的异步任务、正在执行的同步任务、准备执行的异步任务
先看一张流程图
Dispatcher
的整个执行流程就如上图所示,下面来结合源码分别介绍。
// 异步请求
call.enqueue(new Callback() );
// 这个时候会执行 RealCall 下面的方法
这个时候就进入 Dispatcher
分发器
重点来了
首先这个方法是个同步方法,有个判断,判断这个请求是放入 running
队列还是 ready
队列。
图中的1 就是判断条件,如果 running 队列中的 call 小于最大请求数(默认 64)并且对同一地址的请求小于 最大主机请求数(默认5),这个时候就放入 running
队列,直接交给线程池来执行 请求。否则加入 ready
队列,等待请求。
然后看 executorService().execute(call)
这一步其实就是交给线程池执行,最终执行的是 AsyncCall
的 execute()
方法
注意这个方法是在子线程中执行的。
1: 是真正的触发网络请求,进入下一个核心点 “拦截器”。(后面讲解)
2:可以看到 2 是在 finally
中执行的,也就是总是会执行到。
1:执行完毕后就把 call 从 runing 队列中移除了,然后执行 2
这里会根据条件循环判断 ready
队列中的 call 是否能添加到 running
队列中执行。
到此整个分发器的执行流程就结束了!
总结
对于 Dispatcher
分发器核心点就是一个线程池、维持请求队列。
添加一个请求的时候会判断正在请求的数量,如果条件满足就放入线程池执行,否则放入等待队列,等待执行。
后面我们会继续介绍下一个核心—–拦截器
文章来源于互联网:okhttp核心原理分析(1)
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=16915,转载请注明出处。
评论0