构建者模式
在创建OkHttpClient时,用到了构建者模式。就是在OkHttpClient对象中加入了一个Builder的内部类,在初始化时可以传递和构建一些内部数据。
下面我们来利用构建者模式简单来实现一个对象的初始化,看看其在构建对象时的优势何在。
public class Person {
private final String name;
private final int age;
private final float height;
public Person() {
this(new Builder());
}
public Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.height = builder.height;
}
public Builder newBuilder() {
return new Builder(this);
}
public static class Builder {
private String name;
private int age;
private float height;
public Builder(Person person) {
name = person.name;
age = person.age;
height = person.height;
}
public Builder() {
name = "lisa";
age = 15;
height = 156.5f;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Person build() {
return new Person(this);
}
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public float getHeight() {
return height;
}
}
如上所示,优点如下:
第一,person对象不用理会具体的数据初始化与内部数据的管理;
第二,结构清晰明了,分工明确;
第三,使用简单,创建对象时可修改不同属性。
在来看看具体使用如下:
Person person = new Person().newBuilder()
.name("tom")
.age(17)
.build();
发送请求入口
初始化OkHttpClient后,实际上利用RealCall对象发起请求,调用了RealCall对象的enqueue方法
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
RealCall初始化的时候传入了三个变量,并且初始化了一个拦截器。
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
最终通过调度器Dispatcher对象,利用线程池进行网络请求
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
拦截器的添加
通过线程池调用了AsyncCall类中的execute方法,并在该方法中调用了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);
}
然后再来看RealInterceptorChain.proceed()方法中的重要逻辑。
...
// 在RealInterceptorChain.proceed()方法中,会新创建一个RealInterceptorChain对象
//,其中index自增1,用于下次proceed方法调用时,启用下一个拦截器的intercept方法;
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);
...
然后在拦截器的intercept方法中调用新的RealInterceptorChain对象的proceed方法,形成一个闭环链式调用。
到这就明白了,为什么在拦截器中一定要调用RealInterceptorChain.proceed()方法的原因了,因为它是链式闭环上的一个环节,如下图:
最终进入到最后一个拦截器CallServerInterceptor中,在这里面进行真正的网络请求,之前所有拦截器中所有对request和response的修改最终集合到这一个拦截器中,这种设计挺巧妙的,而且逻辑和层次很清晰。
下一篇将重点介绍一下CallServerInterceptor这个网络请求的拦截器以及其他几个内部的拦截器的具体实现。
最后欢迎大家提问一起讨论,也欢迎指出文中错误,谢谢!
网友评论