okhttp-源码解析

如何导入 okhttp 源码?

okhttp 源码工程是一个 maven 构建的 java 工程,不支持 android studio 导入(自己折腾了使用了 android studio 好久发现根本编译不过去,网上有的文章说支持 android studio 导入,误人子弟。。比如.
okhttp 源码工程需要使用 IntelliJ IDEA 导入。具体可参考:IntelliJ IDEA导入 OkHttp
按照该链接编译成功并运行:

源码分析

现在就可以打断点进行调试了。
以 GetExample.java 文件里发送 get 请求为例,来分析一下 okhttp 的执行流程。
GetExample.java:

1
2
3
4
5
6
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}

代码按照如下顺序依次执行:execute() -> getResponseWithInterceptorChain(),重点分析 getResponseWithInterceptorChain():

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

上面的代码展示了 okhttp 核心流程:不同层次的拦截器通过 责任链模式 对 Request 和 Response 进行处理。
如果不清楚责任链模式,可参考责任链模式。按照我的理解,责任链模式是一个事件传递过来以后,会有相应的对象进行处理,具体是哪个或者哪些对象处理需要根据实际情况进行判断。okhttp 里的责任链模式可见如下伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Response getResponseWithInterceptorChain() throws IOException {
// 第一次传入的是 0 代表执行第一个拦截器
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,...);
return chain.proceed(originalRequest);
}
chain.proceed()
{
//递增执行后面拦截器的代码
RealInterceptorChain next = new RealInterceptorChain(index + 1);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
}
interceptor.intercept(Chain chain)
{
chain.proceed(originalRequest);
}

拦截器是 OkHttp 的精髓
client.interceptors() ,首先加入 interceptors 的是用户自定义的拦截器,比如修改请求头的拦截器等;
RetryAndFollowUpInterceptor 是用来重试和重定向的拦截器,在下面我们会讲到;
BridgeInterceptor 是用来将用户友好的请求转化为向服务器的请求,之后又把服务器的响应转化为对用户友好的响应;
CacheInterceptor 是缓存拦截器,若存在缓存并且可用就直接返回该缓存,否则会向服务器请求;
ConnectInterceptor 用来建立连接的拦截器;
client.networkInterceptors() 加入用户自定义的 networkInterceptors ;
CallServerInterceptor 是真正向服务器发出请求且得到响应的拦截器;
最后在聚合了这些拦截器后,利用 RealInterceptorChain 来链式调用这些拦截器。

上面只是展示了大致的流程,具体还有很多细节值得研究。