okhttp3源码解析-全体流程
前语
最近有时间看了看okhttp的源码,之前基本是通过别人的书本、博客去学习源码的,这次是彻底自己去看、去探索,还挺有意思的,这儿略微记录下。
okhttp3的首要流程
要研讨一个凌乱的源码结构,首先要搞定它的首要流程,知道个大约,再去研讨细节,这儿从网上找了一张图片,我觉得把okhttp的流程画的很清楚了: ![pic](img-blog.csdnimg.cn/ba1a19fd586… =300x) 然后我们再看下okhttp的一般调用状况:
// 1,创建OkHttpClient
OkHttpClient httpClient = new OkHttpClient.Builder().build();
// 2,创建Request
Request request = new Request.Builder().url("xxx").build();
// 3,创建Call
Call call = httpClient.newCall(request);
// 4,运用call主张央求:
// 同步运用
Response response = call.execute();
// 异步央求
call.enqueue(callback)
下面我们就根据这四个步骤去查看源码,理解其间的规划思想。
源码分析
创建OkHttpClient
制作者方法,规划方法了,我这儿不讲,只讲在OkHttpClient的运用。这儿实践就三部分内容:
- 参数及setter和getter函数
- 结构函数,用于创建参数的默认值
- build函数,调用OkHttpClient结构传入builder创建实例 这儿就可以完结只设置部分参数创建OkHttpClient实例的功用。
创建Request
这儿也运用了制作者方法,和上面相似,需求留心的是request是不行修正的,看下其阐明:
An HTTP request. Instances of this class are immutable if their body is null or itself immutable.
创建Call
前面创建了OkHttpClient和Request的实例,都还没有到中心代码,接下来是实践内容:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
这儿直接调用RealCall创建了一个RealCall方针,代码进入了RealCall内部的static方法,这儿做了两件事:
- 调用RealCall的构建方法创建了一个RealCall方针
- 向OkHttpClient中传入了一个eventListener
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的构建方法:
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
this.timeout = new AsyncTimeout() {
@Override protected void timedOut() {
cancel();
}
};
this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
}
这儿向RealCall内设置了传入的参数,并创建了retryAndFollowUpInterceptor和timeout方针。retryAndFollowUpInterceptor这个拦截器比较重要,需求留心下它是在这儿创建的,后边会详解这个拦截器。关于timeout这个特色,我没有花时间去研讨,不过可以供给一个别人写的很好的博文,有爱好的读者可以看下:
/post/696246…
eventListener工作监听
eventListener尽管和央求的主流程没什么太大关系,但是这个也是OkHttp一个强壮的功用,它会在每个功用调用的时分提示工作发生的状况,可以查看下其间的方法:
运用call主张央求
前面通过三步操作得到了一个RealCall的实例,终究一步就是通过RealCall去主张同步或异步央求,下面我们先看同步央求,再去看异步央求,尽管异步央求麻烦了一些,但是终究都会汇聚在getResponseWithInterceptorChain方法。
同步央求
同步央求通过调用RealCall的execute方法得到Response,这儿运用executed验证了央求是否已实行,并设置了超时计时、工作调用等。
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
timeout.enter();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
e = timeoutExit(e);
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
这儿我们偏重留心try-catch内部的内容,这儿又做了两件事,一是调用OkHttpClient内的dispatcher实行当时RealCall,二是通过getResponseWithInterceptorChain获取response。 点开dispatcher的executed方法,里边只是将RealCall方针保存到一个数组里去了:
/** Used by {@code Call#execute} to signal it is in-flight. */
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
关于Dispatcher我们后边再讲,先看下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);
}
这儿就通过一系列的拦截器,通过责任链的方法处理,终究得到了Response,看起来很简单,我们暂时就以为这儿就拿到了Response,责任链内的代码后边博文研讨,下面先看异步央求。
异步央求
异步央求通过OkHttpClient的enqueue方法,传入responseCallback得到成果,代码如下:
@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));
}
这儿和同步央求的execute相似,但是终究是通过调用dispatcher的enqueue完结调用,传入了封装responseCallback的AsyncCall方针,下面我们看下AsyncCall方针:
final class AsyncCall extends NamedRunnable {
// 省掉部分代码
/**
* Attempt to enqueue this async call on {@code executorService}. This will attempt to clean up
* if the executor has been shut down by reporting the call as failed.
*/
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
executorService.execute(this);
success = true;
} catch (RejectedExecutionException e) {
InterruptedIOException ioException = new InterruptedIOException("executor rejected");
ioException.initCause(e);
eventListener.callFailed(RealCall.this, ioException);
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
@Override protected void execute() {
boolean signalledCallback = false;
timeout.enter();
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) {
e = timeoutExit(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);
}
}
}
这儿省掉了部分代码,我们偏重重视下executeOn和execute两个方法。实践上AsyncCall就是一个Runnable,它的run方法里边会实行execute方法。 再来看executeOn方法,除掉一些反常处理,实践就是调用了executorService的execute方法实行AsyncCall这个Runnable,这儿的目的就是供给一个线程池来实行AsyncCall的execute()代码。 继续看execute方法,再次忽略反常处理,实践就是调用了getResponseWithInterceptorChain方法获得response,只是这个execute方法实行在指定线程池,也就是说完结了异步实行。
client.dispatcher().enqueue(new AsyncCall(responseCallback));
这儿分析了AsyncCall这个类对responseCallback的封装,回过头来,我们再看下dispatcher的enqueue方法做了什么:
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
}
promoteAndExecute();
}
这儿也比较简单,异步嘛,先加锁,再把AsyncCall存入数组里边,紧接着调用了promoteAndExecute()来推进代码实行。这儿我们就在下面的Dispatcher中偏重分析了。
Dispatcher
前面讲到的同步央求和异步央求,都是通过dispatcher去实行,再通过getResponseWithInterceptorChain拿到Response的,下面我们就来研讨下这个Dispatcher,忽略部分功用,我们偏重看下下面几个内容。
数据域
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<>();
这儿忽略了最大央求数、同域名最大连接数和无任务时处理的idleCallback。executorService通过调用executorService()方法得到,是异步实行的线程池。 三个Deque对应着工作的同步队伍、准备的异步队伍、工作的异步队伍,留心工作的队伍包含了取消但未结束的Call,其间同步队伍保存的是RealCall,而异步队伍保存的是AsyncCall(Runnable)。
方法域
方法域我们偏重介绍下一下promoteAndExecute和finished方法,前面现已讲到同步央求和异步央求调用enqueue和executed只是将任务放到队伍中去,异步央求会再实行下promoteAndExecute方法,下面具体介绍:
/**
* Promotes eligible calls from {@link #readyAsyncCalls} to {@link #runningAsyncCalls} and runs
* them on the executor service. Must not be called with synchronization because executing calls
* can call into user code.
*
* @return true if the dispatcher is currently running calls.
*/
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
// 从ready列表中拿出call存到实队伍表
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
// 调度实行
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
return isRunning;
}
promoteAndExecute就分两步,先将异步任务从ready队伍中取出,并放到running的队伍中,第二步再实行其间的任务,并不是很凌乱,executeOn实行就到AsyncCall的execute方法了。
/** Used by {@code AsyncCall#run} to signal completion. */
void finished(AsyncCall call) {
finished(runningAsyncCalls, call);
}
/** Used by {@code Call#execute} to signal completion. */
void finished(RealCall call) {
finished(runningSyncCalls, call);
}
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
boolean isRunning = promoteAndExecute();
if (!isRunning && idleCallback != null) {
idleCallback.run();
}
}
finished方法通过泛型的方法完结了对同步任务和异步任务的结束,这儿还工作了下idleCallback。
运用call主张央求——小结
至此,同步央求和异步央求的全体流程就差不多结束了,逻辑进入到了几个拦截器的责任链中,我们下篇博文分析,这儿略微小结下. 同步央求和异步央求,都通过了两步,一是存入dispatcher的队伍中,二是通过getResponseWithInterceptorChain拿到成果,异步央求会在dispatcher中通过线程池实行,并将getResponseWithInterceptorChain方法带到异步线程。
下一篇
okhttp3源码解析(2)-拦截器 I