OkHttp 拾遗
2017-10-18 本文已影响19人
spiritTalk
(一)Interceptor chain
OkHttp 的 Interceptor chain 是比较特色的一个东西。我们通过添加自定义的 Interceptor 可以对请求的前、后做一些额外的拦截处理,然而实际上 OkHttp 框架的核心流程也是通过它实现的,以下是 RealCall 中的 getResponseWithInterceptorChain() 方法:
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
// 用户自定义的 interceptor
interceptors.addAll(client.interceptors());
// 负责失败重试以及重定向的
interceptors.add(retryAndFollowUpInterceptor);
/** Bridges from application code to network code.
* First it builds a network request from a user request.
* Then it proceeds to call the network.
* Finally it builds a user response from the network response. */
interceptors.add(new BridgeInterceptor(client.cookieJar()));
/** Serves requests from the cache and writes responses to the cache. */
interceptors.add(new CacheInterceptor(client.internalCache()));
/** Opens a connection to the target server and proceeds to the next interceptor. */
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
/** This is the last interceptor in the chain. It makes a network call to the server. */
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}
Interceptor chain 是个 责任链模式
它包含了一些命令对象和一系列的处理对象,每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。
Interceptor 便是这样,它首先实现自己的职责,比如 BridgeInterceptor 首先通过客户端的 request 创建一个 Request.Builder,然后调用下一个 Interceptor(也就是 CacheInterceptor,可以参考下图中 Interceptor 的调用顺序) 的 proceed 来得到 response,
Response networkResponse = chain.proceed(requestBuilder.build());
最后构建一个新的 Response.Builder 并返回。
OkHttp 流程图其实 Interceptor 的设计也是一种分层的思想,每个 Interceptor 就是一层,分层简化了每一层的逻辑,每层只需要关注自己的责任(单一原则思想也在此体现),而各层之间通过约定的接口/协议进行合作(面向接口编程思想),共同完成复杂的任务。
(二)自定义 Interceptor
- 比如请求中添加统一的 header 和 QueryParameter;
- 没有网络的情况下,尝试使用 cache。
……
private static class RequestInterceptor implements Interceptor {
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request.Builder requestBuilder = chain.request().newBuilder();
requestBuilder.addHeader("os_name", "Android");
……
return chain.proceed(requestBuilder.build());
}
}