OkHttp3 源码解析

编程入门 行业动态 更新时间:2024-10-23 17:28:41

OkHttp3 <a href=https://www.elefans.com/category/jswz/34/1770099.html style=源码解析"/>

OkHttp3 源码解析

参考地址

调用方式

同步调用

@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);}
}

异步调用

void enqueue(Callback responseCallback, boolean forWebSocket) {synchronized (this) {if (executed) throw new IllegalStateException("Already Executed");executed = true;}client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));
}

总体架构

接口层

OKHttpClient 全局维护一个实例,对全局OkHttp 进行设置

Call 表示一次请求执行,分为同步的ReallCall及AsyncCall

协议层

处理特定的协议逻辑,OkHttp支持Http1/Http2/WebSocket协议

连接层

管理网络连接,网络连接请求,服务返回

  • RealConnection 描述一个Socket的连接请求。ConnectionPool 缓存了多个Connection。
  • StreamAllocation表示一次全新的网络请求(一个Call请求可能包含有多个StreamAllocation ,比如重定向)

缓存层

管理本地缓存,当本地有可用缓存时,直接采用本地的以节约流量

I/O层

表示数据的实际读写,采用OKIO

Iterceptor 拦截器层

拦截器逻辑

首先由getResponseWithInterceptorChain 把系统及自定义的拦截器传入
Response getResponseWithInterceptorChain() throws IOException {// Build a full stack of interceptors.List<Interceptor> interceptors = new ArrayList<>();interceptors.addAll(client.interceptors());interceptors.add(retryAndFollowUpInterceptor);interceptors.add(new BridgeInterceptor(client.cookieJar()));interceptors.add(new CacheInterceptor(client.internalCache()));interceptors.add(new ConnectInterceptor(client));if (!forWebSocket) {interceptors.addAll(clientworkInterceptors());}interceptors.add(new CallServerInterceptor(forWebSocket));Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest);return chain.proceed(originalRequest);}
调用 RealInterceptorChain 的process 方法轮训每个拦截器
public final class RealInterceptorChain implements Interceptor.Chain {public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,RealConnection connection) throws IOException {......// Call the next interceptor in the chain.RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request);Interceptor interceptor = interceptors.get(index);Response response = interceptor.intercept(next);...... return response;}
}

RetryAndFollowUpInterceptor

  • 访问失败后进行重试
  • 对服务器要求重定向的情况下进行连接复用

BridgeIterceptor

  • 设置内容长度及类型
  • 设置cookie
  • 设置gzip并在获取response 后进行释放
  • 设置其他报头

CacheInterceptor

  • 增加符合网络要求的cache
  • 更新服务器的最新cache
  • 当前cache失效则输出cache

ConnectInterceptor

CallServerInterceptor

整体流程

任务队列

同步

直接执行

异步队列
client.newCall(request).enqueue();
// 具体执行
synchronized void enqueue(AsyncCall call) {if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {//添加正在运行的请求runningAsyncCalls.add(call);//线程池执行请求executorService().execute(call);} else {//添加到缓存队列排队等待readyAsyncCalls.add(call);}
}
  • 若线程数未达到最大请求则通过线程池直接执行
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
  • 若线程数达到最大请求则加入等待队列,当其他线程执行完成后调用client.dispatcher().finished(this); 来继续执行等待的队列

缓存

Http 缓存策略

  • Expires 超时时间,当访问服务器时比较超时时间,若未超过直接返回缓存结果
  • Cache-Control 表示当前资源的有效期
  • 条件GET请求
客户端第一次请求时,服务器返回:Last-Modified: Tue, 12 Jan 2016 09:31:27 GMT
当客户端二次请求时,可以头部加上如下header:If-Modified-Since: Tue, 12 Jan 2016 09:31:27 GMT
如果当前资源没有被二次修改,服务器返回304告知客户端直接复用本地缓存。
  • Etag
ETag是对资源文件的一种摘要,可以通过ETag值来判断文件是否有修改。当客户端第一次请求某资源时,服务器返回:ETag: "5694c7ef-24dc"
客户端再次请求时,可在头部加上如下域:If-None-Match: "5694c7ef-24dc"
如果文件并未改变,则服务器返回304告知客户端可以复用本地缓存。

更多推荐

OkHttp3 源码解析

本文发布于:2024-02-06 22:44:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1751534.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:源码

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!