简要总结一下OKHttp框架的整体流程,结合其中用到的设计模式进行说明。
1. 使用方式
//1.创建Client
OkHttpClient client = new OkHttpClient();
//2.创建请求
Request request = new Request.Builder()
.url("xxx")
.build();
//3.执行(同步or异步)
okHttpClient.newCall(request).execute();
okHttpClient.newCall(request).enqueue(responseCallback);
2. 源码设计模式解析
2.1 OKHttpClient和Request对象的实例化
OKHttpClient和Request对象包含大量的属性,通过Builder模式按需配置,方便地创建对象。
@Request.Builder
public static class Builder {
HttpUrl url;
String method;
Headers.Builder headers;
RequestBody body;
Object tag;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
Builder(Request request) {
this.url = request.url;
this.method = request.method;
this.body = request.body;
this.tag = request.tag;
this.headers = request.headers.newBuilder();
}
public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}
//省略...
}
@OKHttpClient 中包含大量的请求过程的重要属性,可通过Builder来配置
class OKHttpClient {
final Dispatcher dispatcher;
final @Nullable Proxy proxy;
final List<Protocol> protocols;
final List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors;
final List<Interceptor> networkInterceptors;
final EventListener.Factory eventListenerFactory;
final ProxySelector proxySelector;
final CookieJar cookieJar;
final @Nullable Cache cache;
final @Nullable InternalCache internalCache;
final SocketFactory socketFactory;
final @Nullable SSLSocketFactory sslSocketFactory;
final @Nullable CertificateChainCleaner certificateChainCleaner;
final HostnameVerifier hostnameVerifier;
final CertificatePinner certificatePinner;
final Authenticator proxyAuthenticator;
final Authenticator authenticator;
final ConnectionPool connectionPool;
final Dns dns;
final boolean followSslRedirects;
final boolean followRedirects;
final boolean retryOnConnectionFailure;
final int connectTimeout;
final int readTimeout;
final int writeTimeout;
final int pingInterval;
}
2.2 okHttpClient.newCall创建Call对象
@Override
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
这里看到OKHttpClient类实现了Call.Factory接口,方法中创建了Call的实现类RealCall。
@Call.Factory
interface Factory {
Call newCall(Request request);
}
这里用到了工厂方法模式,Factory接口提供newCall方法,不同的工厂实现类可以继承来生产Call类型的对象。目前只有OKHttpClient一个工厂实现类,满足开闭原则,以后可以直接添加其他工厂来生成不同的Call,方便扩展。
2.3 Call执行
上一步生成的RealCall开始执行,这里选择同步执行的方式来举例往下查看流程,异步流程类似(只是交给dispatcher放到线程池里执行)
@RealCall#execute
@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);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
逻辑非常简单,核心就一句话: Response result = getResponseWithInterceptorChain()
,顾名思义这里就是通过一层层拦截器最终获取到Response,整个流程结束。
2.4 拦截器的实现
OKHttp网络请求流程的核心部分,使用了责任链模式来完成请求发送者和请求处理者的解耦(只需将请求发到链上即可,无须关系处理的细节)。
@RealCall#getResponseWithInterceptorChain
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);
}
首先,构造了一个interceptors列表,其中加入了一些默认的拦截器,client.interceptors和client.networkInterceptors为自定义的拦截器(构造OKHttpClient时加入),所有拦截器都实现了Interceptor接口。
然后,构造了一个职责链 RealInterceptorChain持有了所有的拦截器,然后将请求发到职责链上。
@RealInterceptorChain#proceed
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,RealConnection connection) throws IOException {
//...
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
//...
return response;
}
处理的逻辑很简单:取出index所在的拦截器,执行intercept方法进行拦截,传入的参数为新构造的职责链(index+1,指向了下一个拦截器)。
UML图如下:
最后,写一个简单的自定义拦截器,看下大概的流程:
public class TestInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request(); //取出request
//请求前拦截进行一些处理...
Response response = chain.proceed(request); //传给下一个拦截器
//响应后拦截进行一些处理...
return response;
}
}
到此,OKHttp的网络请求流程已经完整!
总结
OKHttp网络请求框架的实现很优雅,各个类的职责明确,整个流程跟把大象装在冰箱里一样简单:
1、组装Request
2、Client发送Request(经过各个拦截器的处理)
3、返回Response