该文章是对Okhttp的源码解析
一.OkHttpClient,Request的构建
1.1. OkHttpClient有两种构造方式
1.默认方式
public OkHttpClient() {
this(new Builder());
}
OkHttpClient(Builder builder){
builder.xxx
}
2.builder模式
OkHttpClient
——Builder
public OkHttpClient build() {
return new OkHttpClient(this);
}
通过Builder配置参数,最后使用builder方法返回一个OkHttpClient实例(Ps:这个builder 的设置在我们开发中很好用)
以上使用两种设计模式: 1.Builder模式 2.外观模式
1.2. Request有两种构造方式
唯一的构造函数:
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}
说明必须要先构建一个Request.Builder,然后才能构建
public Builder newBuilder() {
return new Builder(this);
}
//builder===================
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 Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
由此可见,又是builder模式,同时默认了GET请求,同时可以传人Request做完参数,构建相同配置的Request
二.异步请求
不管同步/异步请求,其实质的执行流程除了异步外,基本都是一致的
构建完成Request后,再构建一个Call,使用如下:
Call call = http.newCall(request)
源码:
/**
* Prepares the {@code request} to be executed at some point in the future.
*/
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
注意这个是Override 复写的方法,复写的接口是Call.Factory
interface Factory {
Call newCall(Request request);
}
小结:仅仅定义一个newCall用于创建Call的方法,这里用到工厂模式的思想,将构建的细节交给具体实现,顶层只需要拿到Call对象即可
我们继续看RealCall的方法newRealCall方法做了什么
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
其中:final class RealCall implements Call;就是说Call的本质是:RealCall,同时创建一个evenListener:很明显是一个事件的监听器.
而我们看看RealCall的构造函数,创建rertyAndFollowUpInterceptor过滤器,这个就是OkHttp的巨大亮点,根据这个过滤器,我们可以给okhttp增添很多好的定制化工作
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);//这里就是亮点
}
三.最后就是正式请求(enqueue-异步的,excute-同步的)
3.1 enqueue 源码:在RealCall 里面
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
- 使用synchronized 加入对象锁,excute是判断是否被执行
- captureCallStackTrace():加入了一个用于追踪堆栈信息的callStackTrace,
- eventListener.callStart(this); eventListener起到作用了,调用了callStart方法
- client.dispatcher().enqueue(new AsyncCall(responseCallback));
public Dispatcher dispatcher() {
return dispatcher;
}
返回了一个DisPatcher对象
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
然后看看Dispatcher的成员变量
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
private @Nullable Runnable idleCallback;
/** Executes calls. Created lazily. */
private @Nullable ExecutorService executorService;
/** Ready async calls in the order they'll be run. */
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
...
可以看出,这里的三个队列Deque用于保存Call对象,分别三种状态,异步等待,同步running,异步running;
所以:
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
的意思是正在执行的异步队列个数校园MaxRequest 并且请求同一个主机个数校园MaxRequestsPerHost()时候,则将这个请求加入异步执行队列runningAsyncCall,并用线程池执行这个call,否则加入异步等待队列.
private int runningCallsForHost(AsyncCall call) {
int result = 0;
for (AsyncCall c : runningAsyncCalls) {
if (c.host().equals(call.host())) result++;
}
return result;
}
变量runningAsyncCalls,记录同一个Host的个数(小于5️⃣才能加入异步执行队列),否则就加入异步等待队列
现在重点是AsynCall()
回顾一下public AsynCall(RealCall);所有他是用于realCall的引用,而且他是RealCall的内部类
源码
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
}
他基础与NamedRunnabl ,NamedRunnable基础与Runnable;可以看出,这里讲执行的线程额名字设为我们在构造方法中的名字,接着执行execute,其实就这里run方法调用的(同时这里讲当前执行额线程的名字设为我么我们在构造方法中 传人的名字)
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
然后回到AsyCall中的excute()方法
@Override protected void execute() {
boolean signalledCallback = false;
try {
//这里就是网络请求返回Response 的方法
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
小结:RealCall,做完成参数生成AsynCall;AsynCall 根据不同情况放在在Dispather 的不同堆栈中(分别是,运行,等待)中;
AsynCall继承runnable,runnable 最终调用excute()方法;而excute方法就是执行网络请求的(无论是异步/同步);而执行网络
请求最重要的方法是:getResponseWithInterceptorChain()方法,该方法返回Response ;
那么就是说所谓的网络请求的是执行:getResponseWithInterceptorChain()方法直接抛每个,可以说 getResponseWithInterceptorChain就是说 OkHttp的精髓了.
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,就是使用Interceptor的方法将request 层层处理,以下是默认拦截器的作用
拦截器名称 | 用处 |
---|---|
retryAndFollowUpInterceptor | 失败和重定向拦截器 |
BridgeInterceptor | 封装request和response过滤器 |
CacheInterceptor | 缓存相关的过滤器 |
ConnectInterceptor | 负责和服务器建立连接,连接池等 |
networkInterceptors | 配置 OkHttpClient 时设置的 networkInterceptors |
CallServerInterceptor | 负责向服务器发送请求数据、从服务器读取响应数据(实际网络请求) |
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
。。。
// 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构造函数传进来的,初始为0;然后增加,如果index 穿过过滤器个数抛出异常,后面new一个RealInterceptorChain,接着
获取index的interceptor,并调用intercept方法,传人新new的next对象;
其实就是这个RealInterceptorChain就是一个包装了请求的的包装类,我是使用递归的方法,对拦截器的集合的遍历
Q:那么他们是怎么实现每个拦截器都能执行一个遍历的呢?
A:原因在:每个拦截器复写intercept方法,里面执行proceessed,同时该Chain 的构造函数index+1,一直到拦截器集合超出就停止
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
。。。暂时没必要看。。。
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
这里讲RealInterceptionChain给interceptor层层传递,就是经典的责任链设计模式
四.同步请求
@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);
}
}
也是调用getResponseWithInterceptorChain()
以下是OkHttp的整个调用的流程图