一. 深入OkHttp源码
1. Builder() 执行
内部类Builder中的各种初始化
List<Interceptor> interceptors = new ArrayList<>();等
1)dispathcer初始化
内部最大请求数
每个Host最大请求数
三个Deque(就绪的异步请求 将被按顺序执行、运行中的异步请求 包括已取消 但还没结束的请求、运行中的同步请求 包括已取消但还未完全结束的请求)
2)DefaultProtocol :选择协议,1.1/2.0等
这里的Protocol是个枚举类包括了1.0 、1.1、h2、spdy/3.1
3)connectionSpecs
指定HTTP流量通过的套接字连接的配置。
与HTTPS TLS、SSL相关。
4)interceptors
主要业务逻辑均通过拦截器来实现
5)EventListener
指标事件的***。扩展此类以监视数量,大小和持续时间
6)ProxySelector
连接时,选择要使用的代理服务器(如果有)URL引用的网络资源。代理选择器是一个此类的具体子类,并通过调用注册 {@link java.net.ProxySelector #setDefault setDefault}方法。当注册代理选择器时,例如,子类URLConnection类应该调用{@link #select select}
每个URL请求的方法,以便代理选择器可以决定如果应使用直接或代理连接。链接方法返回集合上的迭代器首选连接方法。
7)CookieJar
这是个接口。内部有saveFromResponse方法,两个参数HttpUrl、List<Cookie>
8)Cache
缓存对文件系统的HTTP和HTTPS响应,以便可以重用它们,从而节省时间和时间带宽。
为了测量缓存有效性,该类跟踪三个统计信息:
requestCount() 请求计数:HTTP的数量,自创建此缓存以来发出的请求。
networkCount() 网络计数:需要网络使用的请求。
hitCount() 命中数:这些请求的数量其响应由缓存提供。
有时,请求将导致条件缓存命中。如果缓存包含响应的陈旧副本,则客户端将发出条件GET。然后,服务器将发送更新的响应(如果已更改),或者如果客户端的副本仍然有效则发送短的“未修改”响应。此类响应会增加网络计数和命中计数。提高缓存命中率的最佳方法是将Web服务器配置为返回可缓存的回复。虽然此客户端尊重所有缓存标头,但它不会缓存部分响应。
强制网络响应
在某些情况下,例如在用户单击“刷新”按钮之后,可能需要跳过缓存,并直接从服务器获取数据。要强制完全刷新,请添加 no-cache指令:如果只需要强制服务器验证缓存的响应,请使用更多高效 max-age = 0指令代替:
强制缓存响应
有时你会想要显示资源,如果它们立即可用,但不是。
这可以使用,以便您的应用程序可以在等待最新数据时显示某些下载。要将请求限制为本地缓存的资源,添加only-if-cached指令。
具体的缓存实现还是使用DiskLruCache
8.1 DiskLruCache
在文件系统上使用有限空间的缓存。每个缓存条目都有一个字符串键
和固定数量的值。每个键必须与正则表达式匹配[a-z0-9 _-] {1,64}。
值是字节序列,可以作为流或文件访问。每个值的长度必须介于0和Integer.MAX_VALUE 之间。
缓存将其数据存储在文件系统上的目录中。该目录必须是缓存专用的;缓存可能会删除或覆盖其目录中的文件。多个进程同时使用同一缓存目录是错误的。
此缓存限制它将存储在文件系统上的字节数。当存储的字节数超过限制时,缓存将删除后台中的条目,直到满足限制。限制并不严格:缓存可能会在等待时暂时超过它要删除的文件。该限制不包括文件系统开销或缓存日志对空间敏感的应用应设置一个保守的限制。
客户端调用 edit 来创建或更新条目的值。一个条目一次只能有一个editor;如果某个值无法编辑,那么 edit 将返回null。当创建一个条目时,必须提供一整套值;如有必要,空值应用作占位符。在编辑条目时,不必为每个值提供数据;值默认为其先前的值。
每个edit调用都必须通过调用 Editor commit方法或Editor abort方法进行匹配。提交是原子的:读取会观察到之前或之后的完整值集。提交,但从不混合价值观。
客户端调用get来读取条目的快照。读取将观察get被调用时的值。通话后的更新和删除不会影响正在进行的读取。
该类可以容忍一些I / O错误。如果文件系统中缺少文件,则将从缓存中删除相应的条目。如果在写入缓存值时发生错误,则edit将以静默方式失败。调用者应该通过捕获IOException并正确响应来处理其他问题。
具体用法:https://blog.csdn.net/guolin_blog/article/details/28863651
9)SocketFactory
顾名思义,这是创建Socket的类。
10)SSLSocketFactory
Https准备的Socket构建类
isTLS、X509TrustManager,checkServerTrusted,校验服务器是否可信
2. 网络请求部分
RealCall 有Call接口的具体实现。同步、异步方法分别为execute、enqueue。
execute时候将dispatcher.execute(this)
response通过getResponseWithInterceptorChain()
add了retry、bridge、cache、connect、callServer等拦截器
1)RetryAndFollowUpInterceptor
此拦截器从故障中恢复,并在必要时遵循重定向。它可能会抛出一个
IOException如果call被取消。
重要的一个类StreamAllocation 它串联了三个实体:
Connections
连接与远程服务器的物理套接字连接。这些是建立起来可能很慢,因此必须能够取消连接目前正在连接。(RealConnection)
Streams
分层的逻辑HTTP请求/响应对连接。每个连接都有自己的分配限制,它定义了多少连接可以携带的并发流。 HTTP / 1.x连接可以携带1个流一次,HTTP / 2通常携带多个。
Calls
流的逻辑顺序,通常是初始请求和其后续要求。我们希望将单个呼叫的所有流保持相同连接以获得更好的行为和地点。
内置ConnectionPool其线程池用的是SynchronousQueue(不存储随用随开)
2)BridgeInterceptor
从应用程序代码到网络代码的桥梁。首先,它构建来自用户的网络请求
要求。然后,它继续呼叫网络。最后,它构建了来自网络的用户响应
回应。
添加一些报文的header字段等。
3)CacheInterceptor
提供来自缓存的请求并将响应写入缓存。
CacheStrategy当中主要还是基于http的字头部分,expires、last-modified、ETag、Age等。conditionName “If-None-Match”、“If-Modified-Since”、“If-Modified-Since”。CacheControl类
4)ConnectInteceptor
打开与目标服务器的连接,然后继续执行下一个拦截器。
5)CallServerInterceptor
这是链中的最后一个拦截器。它向服务器进行网络调用。
HttpCodec:Http的编码器
二. Retrofit
1)Retrofit中 首先判断Platform、new Android() / Java8
2)初始化Converters、添加入BuiltInConverters
设置baseUrl部分、判空解析出HttpUrl(url长度,字符数,是否有转义字符 等)
build时
创建defaultCallbackExecutor、defaultCallAdapterFactory
MainThreadExecutor
Handler(Looper looper,Callback callback,boolean async){}
ServiceMethod交给 OkHttpCall也就是okhttp来执行excute / enqueue 具体的网络操作。
loadServiceMethod内