引言
本篇文章为okhttp源码解析系列的第一篇,以日常调用API为主线,进行剖析,梳理流程。不会深入到代码细节方面,为各位看官留下个大致的印象,不至于陷入细节的思维旋涡中。
同步阻塞调用
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
OkHttpClient构造时,会通过public方法Builder初始化数据。Request的实例化通过其静态内部类Builder实现。client.newCall(),实例化call的子类RealCall,由realcall实现execute动作。execute调用getResponseWithInterceptorChain,这个方法中添加了很多的拦截器。我们只关注最后一个拦截器CallServerInterceptor。
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);
return chain.proceed(originalRequest);
}
RealInterceptorChain.proceed中不断递归调用所有的拦截器,当轮训到最后一个拦截器CallServerInterceptor时,才停止递归,返回Response。
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpCodec, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
具有回调的异步调用
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
}
@Override
public void onResponse(Response response) throws IOException {
}
});
异步的话就不是execute而是enqueue,从api名字就能猜出,应该是把callback插入到某个队列中,当这个队列轮训到该callback时,就会execute该request,最后响应callback。让我们一起来看看是否如此吧!
void enqueue(Callback responseCallback, boolean forWebSocket) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
这里将callback包装成AsyncCall。当前正在运行AsyncCall数量小于64,同一host下的AsyncCall数量小于5,就会直接插入了线程池ThreadPoolExecutor中并加入运行队列中。该线程池没有核心线程,但最大线程数为Integer.MAX_VALUE,会立刻启动一个非核心线程来执行任务。若不满足上述条件,就会进入等待队列中,当运行队列中AsyncCall.execute后,会执行Dispatcher.finished方法,试图将等待队列中的AsyncCall加入运行队列中,加入线程池。
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
AsyncCall.execute()获取response的方法就和同步阻塞调用一致了,这里就不再赘述。
@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) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
网友评论