OkHttp3学习(三):execute和Interceptor

回顾

OkHttp3学习(二):发送一个请求中 我们看到了当我们发送一个请求时,通过client.newCall(request)来创建一个RealCall实例,当我们调用RealCallexecute()的时候会调用client对象的dispatcherexecute()方法来执行这个RealCall。当我们调用了RealCallenqueue()方法之后会在内部调用Client对象的dispatcherexecute()方法时创建一个AsyncCall对象,并执行这个AsyncCallexecute方法。不管是client.newCall(request).execute()还是client.newCall(request).enqueue(new Callback(){})我们会发现对应的Call的execute()都会得到执行。

execute()

既然RealCallAsyncCallexecute()都会得到执行,那他们又有什么共同之处呢,相应又是怎么获得的呢?
这是RealCallexecute() 去除了部分代码之后的

1
2
3
4
5
6
7
8
9
10
@Override public Response execute() throws IOException {
captureCallStackTrace();
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
return result;
} finally {
client.dispatcher().finished(this);
}
}

这是AsyncCall去掉部分代码后的execute()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override protected void execute() {
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
//...
} finally {
client.dispatcher().finished(this);
}
}

在这两个代码中我们看到。请求的响应(Responce)都是通过getResponseWithInterceptorChain()方法获取的。其代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
return chain.proceed(originalRequest);
}

在这些代码中我们看到了一堆的Interceptor那么这又是个什么鬼呢?

Interceptor

官方关于Interceptor的介绍:点这里
图片描述
看下这个图。看下这个例子自定义一个Inteceptor应该不成问题了。例子在文档中有。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
final class GzipRequestInterceptor implements Interceptor {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
}
Request compressedRequest = originalRequest.newBuilder()
.header("Content-Encoding", "gzip")
.method(originalRequest.method(), gzip(originalRequest.body()))
.build();
return chain.proceed(compressedRequest);
}
private RequestBody gzip(final RequestBody body) {
return new RequestBody() {
@Override public MediaType contentType() {
return body.contentType();
}
@Override public long contentLength() {
return -1; // We don't know the compressed length in advance!
}
@Override public void writeTo(BufferedSink sink) throws IOException {
BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
body.writeTo(gzipSink);
gzipSink.close();
}
};
}
}

通过下面的方法将一个自定义的Inteceptor加入到请求中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
OkHttpClient client= new OkHttpClient
.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
return null;
}
})
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
return null;
}
}).build();