参考:
https://blog.piasy.com/2016/07/11/Understand-OkHttp/
https://www.jianshu.com/p/82f74db14a18
1.基本调用方法
OkhttpClient client = new OkhttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
2.call:代表一个 request/response 对,定义了 execute enqueue cancel 等操作;一个call只能执行一次
public interface Call {
Request request();
Response execute() throws IOException;
void enqueue(Callback responseCallback);
void cancel();
boolean isExecuted();
boolean isCanceled();
interface Factory {
Call newCall(Request request);
}
}
3.client.newCall(request)
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
4.realCall.execute():真正执行的是 getResponseWithInterceptorChain()
//realcall 的 execute() 方法
@Override public Response execute() throws IOException {
//一个call只能执行一次
//如果想要一个完全一样的 call,可以利用 call.clone 方法进行克隆获取
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
//dispatcher.executed(realcall)只是把 realcall 加入一个双向队列(deque)中等待执行
client.dispatcher().executed(this);
//真正执行网络请求的地方
Response result = getResponseWithInterceptorChain(false);
if (result == null) throw new IOException("Canceled");
return result;
} finally {
//把 realcall 从双向队列(deque)中移除
client.dispatcher().finished(this);
}
}
5.getResponseWithInterceptorChain():添加拦截器
private 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 (!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:按照 index 从 interceptors 中获取拦截器
public final class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;
private final int index;
...
public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream,
Connection connection) throws IOException {
...
// 获取拦截器链中的下一个chain
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpStream, connection, index + 1, request);
//获取当前chain对应的拦截器
Interceptor interceptor = interceptors.get(index);
//让当前的拦截器执行动作,并把下一个chain传递给拦截器,以逐次执行拦截器的功能
Response response = interceptor.intercept(next);
...
}
...
}
//拦截器的基本逻辑
@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//1 Request阶段,该拦截器在Request阶段负责做的事情
//2 调用RealInterceptorChain.proceed(),其实是在递归调用下一个拦截器的intercept()方法
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
//3 Response阶段,完成了该拦截器在Response阶段负责做的事情,然后返回到上一层的拦截器。
return response;
}
6.Interceptor
1)Interceptor 与 chain: Interceptor 是 OkHttp 最核心的一个东西,它不仅仅负责拦截请求进行一些额外的处理(例如 cookie),它还把实际的网络请求、缓存、透明压缩等功能都统一了起来,每一个功能都只是一个 Interceptor,它们再连接成一个 Interceptor.Chain,环环相扣,最终圆满完成一次网络请求。
2)拦截器依次是
interceptors:调用者添加的拦截器;
RetryAndFollowUpInterceptor:顾名思义,负责失败重试和重定向;
BridgeInterceptor:桥接拦截器,负责把用户的request转换为发送给服务器的request,把服务器返回的response转换为用户需要的response;
CacheInterceptor:缓存拦截器
ConnectInterceptor:负责与服务器建立连接(Opens a connection to the target server);
networkInterceptors:也是调用者添加的网络拦截器;
CallServerInterceptor:负责向服务器 发送请求、读取响应数据
3)位置决定了功能,最后一个 Interceptor 一定是负责和服务器实际通讯的,重定向、缓存等功能一定是在实际通讯之前的。
7.ConnectInterceptor:根据源码可以看出,ConnectInterceptor 的功能是实际上获取 connection,而不是典型的拦截功能;
用责任链来描述interceptor更准确,ConnectInterceptor的责任就是获取真正的connection,使责任链后面的interceptor可以使用connection
public final class ConnectInterceptor implements Interceptor {
public final OkHttpClient client;
public ConnectInterceptor(OkHttpClient client) {
this.client = client;
}
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpStream httpStream = streamAllocation.newStream(client, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpStream, connection);
}
}
8.CallServerInterceptor:主要动作如下
1)向服务器发送 request header;
2)如果有 request body,就向服务器发送;
3)读取 response header,先构造一个 Response 对象;
4)如果有 response body,就在 3 的基础上加上 body 构造一个新的 Response 对象;
因此,httpStream.openResponseBody 是真正获取response数据的地方
5)httpStream 实际上是通过okio读取response数据的;okio又是封装了socket
@Override public Response intercept(Chain chain) throws IOException {
HttpStream httpStream = ((RealInterceptorChain) chain).httpStream();
StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
Request request = chain.request();
long sentRequestMillis = System.currentTimeMillis();
httpStream.writeRequestHeaders(request);
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
Sink requestBodyOut = httpStream.createRequestBody(request, request.body().contentLength());
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
}
httpStream.finishRequest();
Response response = httpStream.readResponseHeaders()
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
if (!forWebSocket || response.code() != 101) {
response = response.newBuilder()
.body(httpStream.openResponseBody(response))
.build();
}
if ("close".equalsIgnoreCase(response.request().header("Connection"))
|| "close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
int code = response.code();
if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
throw new ProtocolException(
"HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
}
return response;
}
8.完整流程
9.同步请求与异步请求
//同步请求 realCall.execute
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
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 {
client.dispatcher().finished(this);
}
}
//异步请求 realCall.enqueue(callback)
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
//其中 enqueue(asyncCall)如下
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
10.AsyncCall源码
可以看出,异步的的call实际上也是通过类似的 execute 方法来执行的,最终网络访问还是借助 getResponseWithInterceptorChain 实现的
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
private AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl().toString());
this.responseCallback = responseCallback;
}
String host() {
return originalRequest.url().host();
}
Request request() {
return originalRequest;
}
RealCall get() {
return RealCall.this;
}
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
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 {
client.dispatcher().finished(this);
}
}
}
11.Dispatcher:是一个任务调度器,它内部维护了三个双端队列
readyAsyncCalls:准备运行的异步请求
runningAsyncCalls:正在运行的异步请求
runningSyncCalls:正在运行的同步请求
1)同步请求就直接把请求添加到正在运行的同步请求队列runningSyncCalls中,
2)异步请求会做个判断,如果正在运行的异步请求不超过maxRequests(默认64),而且同一个host下的异步请求不得超过maxRequestsPerHost(默认5个人)个,则将请求添加到正在运行的同步请求队列中runningAsyncCalls,并开始执行请求,否则就添加到readyAsyncCalls继续等待。