该文为个人学习笔记,如有错误,烦请大佬指出~~~
说明:
1.HttpClient 已废弃
2.OkHttp多地址可以采用 ["http://aaaaa","https://bbbbbb"]的方式来配置。
1.总体设计
Request.Builder ->Dispatcher ->HttpEngine(Cache) ->ConnectionPool (Connection)
->Route(Platform) -> Data(Server(Socket))
说明:
--Dispatcher 不断的从RequestQueue中取得请求(Call),根据是否有缓存调用Cache或者Network
--引擎存在两种请求方式:同步(execute)和异步(enqueue)
--同步请求通过Call.execute()直接返 回当前的Response
--异步请求会把当前的请求Call.enqueue添加(AsyncCall)到请求队列中
,并通过回调(Callback) 的方式来获取最后结果
1.Route
--地址的一个封装类
2.Platform
--平台适应性,针对Android2.3到5.0后的网络请求的适配支持
3.Connnection
4.ConnnectionPool
OkhttpClient类的整体设计是采用门面模式,client知晓子模块的所有配置以及提供需要的参数
2.同步与异步的实现
--通过call 封装网络请求
--Call持有OkHttpClient和一份HttpEngine
--每一次的同步或者异步请求都会有Dispatcher的参与
--Call中持有一个HttpEngine。
每一个不同的Call都有自己独立的HttpEngine。
在HttpEngine中主要是各种链路和地址的选择
不同点:
--同步
Dispatcher会在同步执行任务队列中记录当前被执行过得任务Call,
同时在当前线程中去执行Call的getResponseWithInterceptorChain()方法,
直接获取当前的返回数据Response
--异步
Dispatcher内部实现了懒加载无边界限制的线程池方式,
该线程池采用了 SynchronousQueue这种阻塞队列
SynchronousQueue每个插入操作必须等待另一个线程的移除操作,同样任何一个移除操作都等 待另一个线程的插入操作
--多任务队列中是最快处理任务的方式
异步执行是通过Call.enqueue(Callback responseCallback)来执行
,在Dispatcher中添加一个封装了Callback的Call的匿名内部类Runnable来执行当前 的Call
--这里一定要注意的地方这个AsyncCall是Call的匿名内部类
AsyncCall的execute方法仍然会回调到Call的
getResponseWithInterceptorChain方法来完成请求,同时将返回数据或者状态通过Callback来完成
3.拦截器
--观察,修改以及可能短路的请求输出和响应请求的回来。
--通常情况下拦截器用来添加,移除或者转换请求或者回应的头部信息。
4.缓存策略
--OkHttpClient内部暴露了有Cache和InternalCache,InternalCache不应该手动去创建
5.sendRequest()
--对可能的Response资源进行一个预判,如果需要就会开启一个socket来获取资源
6.readResponse()
--涉及与缓存对比
7.HTTP连接
--外部网络请求的入口都是通过Transport接口来完成
该类采用了桥接模式将HttpEngine和HttpConnection来连接起来
--发起请求是在Connection.connect()
实际执行是在HttpConnection.flush()这里进行一个刷入
--重点应该关注一下sink和source,他们创建的默认方式都是依托于同一个socket
8.重连机制
--Call.getResponse()中建立重连机制
--请求连接异常、则进行HttpEngine 恢复、并重新请求。如果恢复失败、则中断请求。
说明:
--HttpEngine.recover()的实现方式是通过检测RouteSelector是否还有更多的routes可以尝试连接,
同时会去 检查是否可以恢复等等的一系列判断。
如果可以会为重新连接重新创建一份新的HttpEngine,同时把相应的链路信息传递过去
--当恢复后的HttpEngine不为空,那么替换当前Call中的当前HttpEngine,执行while的continue,
发起下一次的请求
--HttpEngine.sendRequest()。
这里之前分析过会触发connect()方法,在该方法中会通过 RouteSelector.next()再去找当前适合的Route
next()方法会传递到 nextInetSocketAddress()方法,Network这个接口中有一个对该接口的 DEFAULT的实现域,
而该方法通过工具类InetAddress.getAllByName(host)来完成对数组类的地址解析。
9.Gzip
10.安全性
--连接安全性主要是在HttpEngine.connect()方法
11.平台适应性(Platform.findPlatform)
--利用JAVA的反射原理调用到class的method。最后在各自的平台调用下发起invoke来执行相应方法
学习博客地址:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0326/2643.html