分析源码之前需要先了解几个OkHttp中的概念。
Request
Each HTTP request contains a URL, a method (like GET or POST), and a list of headers. Requests may also contain a body: a data stream of a specific content type.
每一个request含有一个url,一个方法(比如GET或者POST),和一个header列表。request也可能包含一个body:某种特定类型的数据流。
代码中对应Request类。
Response
The response answers the request with a code (like 200 for success or 404 for not found), headers, and its own optional body.
一个response应答一个request,它有一个状态码(比如200表示成功或者404表示未找到),headers,和一个可选的body。
代码中对应Response类。
Call
With rewrites, redirects, follow-ups and retries, your simple request may yield many requests and responses. OkHttp uses Call to model the task of satisfying your request through however many intermediate requests and responses are necessary.
重写,重定位,follow-ups和重试(指请求不成功重新请求),一个简单的request可能衍生出多个requests and responses。
OkHttp使用call来表示这种无论通过多少次内部请求和响应后满足你请求的任务。
就是说你发出网络请求之后,有可能因为第一次没有连接上重试第二次第三次请求,也有可能服务器告诉你这个资源重定位到了其他地址然后去请求其他地址获取结果,等等,这样一次完整的网络请求内部可能会包含多次requests and responses才能获取到最终的结果。我们把这样一次完整的网络请求称之为Call。
代码中对应Call接口。
上代码
OkHttpClient client = new OkHttpClient();
Request asyncRequest = new Request.Builder()
.url("http://www.baidu.com")
.build();
//同步请求
// try {
// client.newCall(asyncRequest).execute();
// } catch (Exception e) {
// e.printStackTrace();
// }
//异步请求
client.newCall(asyncRequest).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("okhttp", response.code() + "");
Log.d("okhttp", response.body().string());
}
});
我们先看看OkHttpClient的默认构建
public OkHttpClient() {
this(new Builder());
}
用了建造者模式
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
在默认的Builder中初始化了一大堆东西。
接着是Request的构建,又是一个建造者,我发现square貌似挺偏爱这个设计模式~
看看Request里面都有些啥
public final class Request {
final HttpUrl url;
final String method;
final Headers headers;
final @Nullable RequestBody body;
final Object tag;
...
}
嗯,url,method,header,body,该有的都有了。
然后调用了OkHttpClient的newCall方法来构建一个call
@Override
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
跟进RealCall的方法里面看看
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;
}
构建并且返回了一个RealCall。
RealCall实现了Call接口,我们真正的网络请求就是在这个类中实现的。
Call接口中,请求方法有两个,execute方法为同步请求,enqueue方法为异步请求。我们分别来看一下RealCall中这两个方法的实现。
同步请求
@Override
public Response execute() throws IOException {
...
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
...
} finally {
client.dispatcher().finished(this);
}
}
请求开始的时候调用了client.dispatcher().executed(this),请求结束又调用了client.dispatcher().finished(this)。
真正产生Response的地方是在getResponseWithInterceptorChain()方法中。
异步请求
@Override public void enqueue(Callback responseCallback) {
...
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
构建了一个AsyncCall,并且传给了client.dispatcher().enqueue方法。
AsyncCall是一个Runnable,其run方法内部调用了AsyncCall的execute方法,我们跟进AsyncCall的execute看看。
@Override
protected void execute() {
boolean signalledCallback = false;
try {
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) {
...
} finally {
client.dispatcher().finished(this);
}
}
可以看到在AsyncCall的execute的方法内,调用了getResponseWithInterceptorChain()来获取Response。
然后调用了responseCallback的成功或者失败的回调,这个responseCallback就是我们调用异步请求时传入的监听回调。
最后调用了client.dispatcher().finished(this)。
结合execute和enqueue的方法调用过程我们可以看出,真正的请求时在getResponseWithInterceptorChain()方法中进行的。
请求开始前,同步请求调用了client.dispatcher().executed方法,异步请求调用了client.dispatcher().enqueue方法;请求结束之后它们都调用了client.dispatcher().finished(this)。
追踪一下client.dispatcher()发现是在OkHttpClient.Builder初始化的时候构建的一个Dispatcher对象,看下它的注释。
Policy on when async requests are executed.
Each dispatcher uses an {@link ExecutorService} to run calls internally. If you supply your own executor...
异步请求何时执行所使用的策略。内部使用一个ExecutorService来运行请求。
对于同步请求,Dispatcher里面的executed方法只是把请求加入了一个队列,finished方法又把它移出了队列,这个就不细说啦。
主要看一下异步请求,
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
runningAsyncCalls是一个队列,存储正在运行中的异步请求;readyAsyncCalls也是一个队列,存储准备运行的异步请求。
上面这段代码表示,如果正在运行中的异步请求队列还没有达到最大数量,把这个请求加入该队列,并且执行executorService().execute(call)语句;否则,把它加入到准备运行的异步请求队列。
我们来看看executorService()是啥
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
这里就很清楚啦,返回了一个线程池。所以,默认情况下OkHttpClient就是用这里构造的线程池来进行异步请求的。
再看Dispatcher里面finish异步请求的逻辑
/** Used by {@code AsyncCall#run} to signal completion. */
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
private void finished(Deque calls, T call, boolean promoteCalls) {
...
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if (promoteCalls) promoteCalls();
...
}
...
}
可以看到,先把它移出了runningAsyncCalls队列,然后执行了promoteCalls()方法。
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
这段代码主要的逻辑是把readyAsyncCalls队列里面的call拿出来放到runningAsyncCalls里面并且执行。
对于Dispatcher的分析就到这里了,下面我们回到RealCall,分析一下真正调用请求的方法getResponseWithInterceptorChain()。
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List 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);
}
这里使用了职责链模式来进行请求。
看下Interceptor的模型。
/**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding
* responses coming back in. Typically interceptors add, remove, or transform headers on the request
* or response.
* 观察,修改,以及短路出去的request和相应回来的response。
* Interceptor典型用法是可以用来增加,移除,或者变换request和response的header。
*/
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
...
}
回到getResponseWithInterceptorChain方法,里面先是使用多个Interceptor创建了一个列表。
其中client.interceptors()和client.networkInterceptors()这两个是我们可以在OkHttpClient的builder里面自行添加的,以实现某些我们想实现的功能,比如添加header,给请求加密,对请求打日志等等。
都是Interceptor,它们有什么不一样的呢?
/**
* Returns an immutable list of interceptors that observe the full span of each call: from before
* the connection is established (if any) until after the response source is selected (either the
* origin server, cache, or both).
*/
public List interceptors() {
return interceptors;
}
/**
* Returns an immutable list of interceptors that observe a single network request and response.
* These interceptors must call {@link Interceptor.Chain#proceed} exactly once: it is an error for
* a network interceptor to short-circuit or repeat a network request.
*/
public List networkInterceptors() {
return networkInterceptors;
}
可以看到前一个是observe the full span of each call,后一个是observe a single network request and response。
前一个是针对整个call来监听的;
后一个是针对一个具体的request/response来监听的,它监听的是网络请求发出时的request及对应的response。
关于call和request的区别请查看本文开头列出的概念。
比如说,如果有一个请求,你设置了可以从OkHttp的缓存中获取且缓存命中了,那么后一个Interceptors将不会被执行,因为根本没有去执行网络请求;但是对于前一个Interceptors来说,是会被执行的,因为它是针对call的,call发出了请求并且收到了返回,无论这个返回是从网络,缓存还是其它的什么地方。
我们看最后一个被加入列表的CallServerInterceptor的说明,This is the last interceptor in the chain. It makes a network call to the server. 这是链中的最后一个interceptor,它向服务器进行了一个网络请求。
/** This is the last interceptor in the chain. It makes a network call to the server. */
public final class CallServerInterceptor implements Interceptor {
...
}
Interceptor列表构建完成后,使用该列表构建了一个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;
}
可以看到,会依次把interceptor列表中的后一个inercepter构建为一个RealInterceptorChain传递给列表中的前一个inercepter,其中的index标志当前进行到了interceptor列表中的第几个。这是一个职责链模式的使用,列表中的interceptor会依次对request进行处理直至最后一个interceptor进行了网络请求,然后倒序逐级处理返回的response。