1. 基本使用
OkHttpClient.Builder clientBuilder = new OkHttpClient().Builder();
clientBuilder.connectTimeout(60,TimeUnit.SECONDS)//链接超时
.readTimneout(15,TimeUnit.SECONDS)//读取超时
.writeTimeout(15,TimeUnit.SECONDS)//写入超时
.interceptors(interceptor)//自定义拦截器
.networkInterceptors(networkInterceptors);//自定义网络连接成功的拦截器
OkHttpClient client = clientBuilder.build();
Request request = new Request().Builder().url(url).build();
Call call = client.newCall(request); //注释一
call.enqueue(new Callback(){ //异步请求
@override
public void onFailure(Call call, IOException e){
}
@override
public void onResponse(Call call, Response response) throws IOException {}
})
2. 原理分析
2.1 newCall
请求操作的起点从client.newCall(request) (注释一)开始
//OkHttpClient 初始化Call的函数
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false);
}
// RealCall 初始化函数
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
可以看出,最终构建返回的是RealCall对象,它是真正执行网络请求的类,实现了Call接口,提供同步请求,异步请求
2.2 同步请求
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);//1
Response result = getResponseWithInterceptorChain();//2
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
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(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());//3
return chain.proceed(originalRequest);//4
}
- Dispatcher OkHttpClient调度器,这里将RealCall实例添加到Dispatcher中
- 通过getResponseWithInterceptorChain()获取响应
- 获取拦截器集合中第一个拦截器任务
- 触发第一个拦截器任务,当任务执行完,会触发下个拦截器。
2.3 异步请求
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));//1
}
- Dispatcher内部维护一个线程池去执行异步任务
Dispatcher.enqueue
sychronized void enqueue(AsyncCall call){
if(runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost){
executorService().execute(call);
}else {
readyAsyncCalls.add(call);
}
}
可以看出,实际上是使用线程池去执行AsyncCall
final class AsyncCall extends NamedRunnable {
@Override
public final void run
{
...
execute();
...
}
// ......
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();//2
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 {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
}
同样是通过getResponseWithInterceptorChain()获取服务器响应
2.4 Interceptor拦截器
-
RetryAndFollowUpInterceptor 重定向拦截器
承担重新请求新url的作用(服务器返回3XX错误码为重定向,可以通过响应头的Location获取新请求的url);
-
BridgeInterceptor 桥拦截器
封装请求头(Content-Type、Connection、Cookie…)与响应头("Content-Encoding…)的信息。
-
CacheInterceptor 缓存拦截器
为网络请求提供缓存功能,加快相同请求的访问速度,减少资源消耗
-
ConnectInterceptor 连接拦截器
负责建立与服务器之间的连接
-
CallServerInterceptor 请求服务拦截器
与服务器进行数据通讯,发送请求,获取响应
CacheInterceptor 缓存拦截器
缓存拦截器主要做了两件事
-
根据Request获取当前已有的Response缓存,可能为null,并根据缓存创建CacheStrategy对象
public final class CacheInterceptor implements Interceptor { // .... @Override public Response intercept(Chain chain) throws IOException { // 根据请求内容通过Cache类判断是否已经存在响应的缓存信息 Response cacheCandidate = cache != null ? cache.get(chain.request()) : null; long now = System.currentTimeMillis(); // 通过请求对象与缓存对象创建缓存策略, CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get(); Request networkRequest = strategy.networkRequest; Response cacheResponse = strategy.cacheResponse; // ... }
-
通过CacheStrategy判断当前缓存中的Response是否失效,如果可用则直接返回,否则调用chain.proceed()继续执行下一个拦截器
// 记录请求过程的相关数据(请求次数、缓存次数....) if (cache != null) { cache.trackResponse(strategy); } if (cacheCandidate != null && cacheResponse == null) { closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it. } // 如果缓存无效,且请求为空,直接返回空的Response if (networkRequest == null && cacheResponse == null) { return new Response.Builder() .request(chain.request()) .protocol(Protocol.HTTP_1_1) .code(504) .message("Unsatisfiable Request (only-if-cached)") .body(Util.EMPTY_RESPONSE) .sentRequestAtMillis(-1L) .receivedResponseAtMillis(System.currentTimeMillis()) .build(); } // 缓存有效,直接讲缓存中的Response返回 if (networkRequest == null) { return cacheResponse.newBuilder() .cacheResponse(stripBody(cacheResponse)) .build(); } Response networkResponse = null; try { // 如果没有缓存,或者缓存失效,则执行下一个拦截器任务,发送网络请求获取Response networkResponse = chain.proceed(networkRequest); } finally { // If we're crashing on I/O or otherwise, don't leak the cache body. if (networkResponse == null && cacheCandidate != null) { closeQuietly(cacheCandidate.body()); } }
CallServerInterceptor请求服务拦截器
请求服务拦截器是OkHttp网络请求部分,其intercept方法如下
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
HttpCodec httpCodec = realChain.httpStream();
StreamAllocation streamAllocation = realChain.streamAllocation();
RealConnection connection = (RealConnection) realChain.connection();
Request request = realChain.request();
long sentRequestMillis = System.currentTimeMillis();
realChain.eventListener().requestHeadersStart(realChain.call());
httpCodec.writeRequestHeaders(request);
realChain.eventListener().requestHeadersEnd(realChain.call(), request);
Response.Builder responseBuilder = null;
// ...
httpCodec.finishRequest();
// 发送请求数据部分
// ...
}
if (responseBuilder == null) {
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(false);
}
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
int code = response.code();
if (code == 100) {
// server sent a 100-continue even though we did not request one.
// try again to read the actual response
responseBuilder = httpCodec.readResponseHeaders(false);
response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
code = response.code();
}
realChain.eventListener()
.responseHeadersEnd(realChain.call(), response);
if (forWebSocket && code == 101) {
// Connection is upgrading, but we need to ensure interceptors see a non-null response body.
response = response.newBuilder()
.body(Util.EMPTY_RESPONSE)
.build();
} else {
response = response.newBuilder()
.body(httpCodec.openResponseBody(response))
.build();
}
// ...
return response;
// 获取请求结果部分
3. 总结
- OkHttp中的同步,异步请求,最终都是由Dispatcher调度器进行分发执行
- 网络请求阶段通过责任链模式,链式调用各个拦截器的intercept( )