您的位置:首页 > 理论基础 > 计算机网络

OkHttp3深度源码解析(一),体会OkHttp3设计模式的妙处

2016-11-07 11:50 267 查看
一、okhttp背景…

二、使用步骤

1、创建OkHttpClient;

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

这一个过程到底做了什么?

最张调用 OkHttpClient(Builder builder)得到实例并赋值。

赋值了哪些参数?

private OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;

boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}

if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = systemDefaultTrustManager();
this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}

this.hostnameVerifier = builder.hostnameVerifier;
this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
certificateChainCleaner);
this.proxyAuthenticator = builder.proxyAuthenticator;
this.authenticator = builder.authenticator;
this.connectionPool = builder.connectionPool;
this.dns = builder.dns;
this.followSslRedirects = builder.followSslRedirects;
this.followRedirects = builder.followRedirects;
this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.writeTimeout = builder.writeTimeout;
}


参数解释:

1)dispatcher:请求的执行器,负责请求的同步执行、异步执行、取消、以及最多可以同时执行的请求数。

包含三个请求队列:

readyAsyncCalls,准备执行的异步请求列队,(当同时请求数大于maxRequests时,会将请求存入到这列队)

runningAsyncCalls:正在执行的异步请求列队(未取消和未结束)

runningSyncCalls:正在执行的同步请求列队(未取消和未结束)

2)proxy:网络的代理设置,可以通过他给网络请求设置代理

3)protocols:支持的Protocol协议,Protocol和Url类似,java.net.URI.getScheme()返回url的协议(http, https, etc),而Protocol.get()返回的协议更加具体(http/1.0,http/1.1,h2,etc)

4)connectionSpecs : 支持套接字连接协议.

5)interceptors: 拦截器。可观察每个调用的全部跨度

6)networkInterceptors : 拦截器。可观察一个网络请求和响应

7)proxySelector :代理服务器选择器

8)cookieJar :提供cookie可持久化操作。

9)cache:缓存

10)internalCache:okhttp的内部缓存,使用者不应该使用它,用cache即可。

11)socketFactory :创建套接字的工厂类

12)sslSocketFactory:创建ssl套接字工厂类

13)certificateChainCleaner:证书

14)hostnameVerifier:主机名验证

15)certificatePinner:约束所信任的证书

16)proxyAuthenticator:身份验证代理服务器

17)authenticator:身份验证代理服务器

18)connectionPool:连接池用于回收利用HTTP和HTTPS连接。

19)dns:dns服务器;默认使用系统的

20)followSslRedirects:是否支持sslhttp重定向,默认true

21)followRedirects:是否支持http重定向,默认true

22)retryOnConnectionFailure:连接失败时是否重试,默认true

23)connectTimeout:连接超时

24)readTimeout:读取超时

25)writeTimeout:写入超时

参数有些多,大致了解可以帮我们更容易理清okhttp整体流程

2、创建Request;

private Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}


参数说明,这个看着清爽:

1)url:请求地址

2)method :请求方法

3)headers :请求头

4)body:请求体

5)tag:请求标记

3、创建Call,

Call = okHttpClient.newCall(Request);

实际上调用了

protected RealCall(OkHttpClient client, Request originalRequest) {
this.client = client;
this.originalRequest = originalRequest;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client);
}


这里添加 retryAndFollowUpInterceptor 拦截器,通过这个拦截实现了重新请求及取消请求功能

4、重头戏来了。(这里先看看异步请求),enqueue(Callback responseCallback);

1)开始执行请求:

synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}


如果已经被执行就抛异常,所以一个call就能调一次execute、enqueue。


2) client.dispatcher().enqueue(new AsyncCall(responseCallback));

调用该请求的client的执行器来执行该请求。

这里先创建了一个Runable的子类AsyncCall。

3)dispatcher 类中

synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}


看看请求列表有没有满。没有满,加入到正在执行列表,然后直接执行。否则放到等待队列。

4)AsyncCall类中,直接在代码中注解了

@Override protected void execute() {
//标记有没有执行回调
boolean signalledCallback = false;
try {
//核心、获取到response,看下面注释
Response response = getResponseWithInterceptorChain();

//如果取消的就直接回调onFailure,传入new IOException("Canceled")异常。
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//最后,结束这个call,看下面
client.dispatcher().finished(this);
}
}

private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if (promoteCalls) promoteCalls();//promoteCalls()是为了在满足要下(正在执行的异步任务数小于maxRequests)把准备请求列里的请求转至正在请求队列,并执行它。
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}

if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();//如果分发器没有需要执行的工作,处理idle状态,会执行该回调
}
}

RealCall类里面
private Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();

//下面是添加一系列拦截器,个人觉得这里是体现okhttp精华所在的胜地,看到这里,都会激动的不要不要的!
interceptors.addAll(client.interceptors());
//网络重试及取消的处理
interceptors.add(retryAndFollowUpInterceptor);
//cookie处理
interceptors.add(new BridgeInterceptor(client.cookieJar()));
//okhttp的内部缓存处理
interceptors.add(new CacheInterceptor(client.internalCache()));
//打开目标服务器的连接
interceptors.add(new ConnectInterceptor(client));

//如果不是forWebSocket,添加网络重试及取消拦截器
if (!retryAndFollowUpInterceptor.isForWebSocket()) {
interceptors.addAll(client.networkInterceptors());
}
网络请求在这个拦截器里面
interceptors.add(new CallServerInterceptor(
retryAndFollowUpInterceptor.isForWebSocket()));

Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}

RealInterceptorChain类中 贴出核心代码
public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream,
Connection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();

Call the next interceptor in the chain.
获取到下个拦截(拦截是从0开关顺序执行的,结后执行是的CallServerInterceptor拦截器,所以在CallServerInterceptor拦截器中就看不到Chain.proceed(Request request)了)
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpStream, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
//让下个拦截去处理所要处理的逻辑
Response response = interceptor.intercept(next);

return response;
}


三、总结

看完后

美妙无穷
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息