一、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;
}
三、总结
看完后
美妙无穷