执行请求流程
1.真正的请求交给了 RealCall 类的execute方法
client.dispatcher().enqueue(new AsyncCall(responseCallback));
dispatcher调度器enqueueAsyncCall,然后通过回调(Callback)获取服务器返回的结果
2.Dispatcher
Dispatcher将call加入到队列中,然后通过线程池来执行call,它是一个任务调度器,内部维护了三个双端队列:
①readyAsyncCalls:准备运行的异步请求
②runningAsyncCalls:正在运行的异步请求
③runningSyncCalls:正在运行的同步请求
新来的请求放队尾,执行请求从队列头部取。
3.线程池
这不是newCachedThreadPool吗?没错,除了最后一个threadFactory参数之外与newCachedThreadPool一模一样,只不过是设置了线程名字而已,用于排查问题。
阻塞队列用的SynchronousQueue,它的特点是不存储数据,当添加一个元素时,必须等待一个消费线程取出它,否则一直阻塞。
通常用于需要快速响应任务的场景,在网络请求要求低延迟的大背景下比较合适。
采用责任链的模式来将每个功能分开,每个Interceptor自行完成自己的任务。
拦截器
利用Builder模式配置各种参数,例如:超时时间、拦截器、缓存等
retryAndFollowUpInterceptor:失败和重定向拦截器
当请求内部抛出异常时,判定是否需要重试
当响应结果是3xx重定向时,构建新的请求并发送请求
BridgeInterceptor:封装request和response拦截
负责把用户构造的请求转换为发送到服务器的请求
把服务器返回的响应转换为用户友好的响应
CacheInterceptor:
当在OkHttpClient中配置了缓存,则将这个Resposne缓存起来
ConnectInterceptor:连接服务,负责和服务器建立连接,负责了Dns解析和Socket连接
CallServerInterceptor:传输http的头部和body数据
addInterceptor 和 addNetworkdInterceptor区别
在OkHttpClient.Builder的构造方法有两个参数,使用者可以通过addInterceptor 和 addNetworkdInterceptor 添加自定义的拦截器
加拦截器的顺序可以知道 Interceptors 和 networkInterceptors 刚好一个在 RetryAndFollowUpInterceptor 的前面,一个在后面
责任链调用图可以分析出来,假如一个请求在 RetryAndFollowUpInterceptor 这个拦截器内部重试或者重定向了 N 次,那么其内部嵌套的所有拦截器也会被调用N次,同样 networkInterceptors 自定义的拦截器也会被调用 N 次。而相对的 Interceptors 则一个请求只会调用一次,所以在OkHttp的内部也将其称之为 Application Interceptor。
采用责任链的模式
将处理者和请求者进行解耦
多个对象都有机会处理请求,将这些对象连成一个链,将请求沿着这条链传递。
在请求到达时,拦截器会做一些处理(比如添加参数等),然后传递给下一个拦截器进行处理。
缓存怎么处理
1.使用OkHttp的缓存
定义一个网络拦截器
Http协议 缓存的控制是通过首部的Cache-Control来控制
only-if-cache: 表示直接获取缓存数据,若没有数据返回,则返回504
有网络时访问服务器
无网络时返回缓存数据
①自定义Interceptor,重写intercept设置header *
②OkHttpClient .cache// 设置缓存路径和缓存容量 *addNetworkInterceptor设置自定义缓存
2.不使用OkHttp的缓存
if (NetworkUtil.isConnected(mContext)) { response = chain.proceed(newRequest); saveCacheData(response); // 保存缓存数据 } else { // 不执行chain.proceed会打断责任链,即后面的拦截器不会被执行 response = getCacheData(chain.request().url()); // 获取缓存数据 }
Okhttp连接池
连接池是为了解决频繁的进行建立Sokcet连接(TCP三次握手)和断开Socket(TCP四次分手)
socket复用有何标准
get
1.http协议
1.在http 1.x协议下,所有的请求的都是顺序的,正在写入数据的socket无法被另一个请求复用 2.http2.0协议使用了多路复用技术,允许同一个socket在同一个时候写入多个流数据
http1.x协议下当前socket没有其他流正在读写时可以复用,否则不行,http2.0对流数量没有限制。
2.域名和http和ssl协议配置需要匹配
put
在连接池中找连接的时候会对比连接池中相同host的连接。
如果在连接池中找不到连接的话,会创建连接,创建完后会存储到连接池中。