OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("www.baidu.com")
.build();
try {
//发送同步请求
okHttpClient.newCall(request).execute();
//发送异步请求
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
@Override
public void onResponse(Call call, Response response) throws IOException {}
});
} catch (IOException e) {
e.printStackTrace();
}
上面这段就是最基础的应用,发送一个get请求。OkHttpClient 有两种创建方式,一种是直接new 一种是OkHttpClient.Builder形式。首先看okHttpClient.newCall(request)
Dispatcher 上层调度
//方法1
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
//方法2
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;
}
// 方法3
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
实例,这个实例对象携带了网络请求的所有信息,包括OkHttpClient
Request
。
@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);
}
}
这是RealCall的同步请求方法,内部就两个核心方法
client.dispatcher().executed(this)
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
是指就是往一个正在运行的同步队列runningSyncCalls
添加了一个RealCall
2. 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);
}
这个方法是OkHttp
发送请求的核心方法,包括 请求数据 和 拦截器的调用都是通过这个方法的。
@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));
}
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
}
promoteAndExecute();
}
这是异步请求的调用方法,基本和同步请求一样只不过少调用了 getResponseWithInterceptorChain
然后调用了调度器的方法,将RealCall 封装成了一个AsyncCall 对象 然后添加到了readyAsyncCalls
将要开始的异步队列中
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
//遍历将要开始异步请求队列
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
// 如果runningAsyncCalls 正在请求异步队列 数大于 最大并发数
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
// 如果runningAsyncCalls 正在请求异步队列 请求主机数大于 最大主机数
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
//添加到list集合 和 runningAsyncCalls队列
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
// 执行 AsyncCall
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
// executorService() 创建一个线程池 执行AsyncCall
asyncCall.executeOn(executorService());
}
return isRunning;
}
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;
}
通过注释可以看到,其实这里做的很简单,就是让一个正在准备异步请求的队列中添加了一个call 也就是request的封装,然后创建了一线程池,最后执行了asyncCall.executeOn
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
// 注释1 执行 ,this实现了AsyncCall extends NamedRunnable
executorService.execute(this);
success = true;
} catch (RejectedExecutionException e) {
// 。。。
} finally {
if (!success) {
// 注释2 如果出现异常 就finish
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
看看他的run方法怎么调用的
//NamedRunnable.java
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
//AsyncCall.java
@Override protected void execute() {
boolean signalledCallback = false;
timeout.enter();
try {
// 注释 1 在一次遇到 getResponseWithInterceptorChain 执行请求
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 {
//注释2 再一次遇到 dispatcher().finished()
client.dispatcher().finished(this);
}
}
getResponseWithInterceptorChain
我们暂且先放置, 先看看dispatcher().finished()
做了什么事。
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();
}
}
可以看出它里面依然是执行了promoteAndExecute
类似一个递归调用,不断的去 runningAsyncCalls
readyAsyncCalls
中去判断,首先判断正在运行的队列是否达到最大请求量,没达到就把readyAsyncCalls取出一个放进去,用线程池执行。
接下来我们在回头看看 调度器逻辑 我们会发现 他其实就是三个队列 和 两个最大请求量参数。
public final class Dispatcher {
private int maxRequests = 64; //最大请求数
private int maxRequestsPerHost = 5; //最大请求主机数
private @Nullable Runnable idleCallback;
/** Executes calls. Created lazily. */
private @Nullable ExecutorService executorService;
/** 将要执行的异步请求队列 */
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/** 正在准备执行的异步请求队列 */
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/** 正在准备执行的同步请求队列 */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
上面的所有逻辑其实都离不开Dispatcher ,其实就是通过控制
readyAsyncCalls
runningAsyncCalls
runningSyncCalls
来执行getResponseWithInterceptorChain()
。Dispatcher
它的核心功能就是管理所有的Call
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);
}
依然回到这段代码 这段代码做了两件事, 第一件 创建了很多拦截器,添加到一个集合中; 第二件 Interceptor.Chain
拦截器链 执行了proceed
方法。
// RealInterceptorChain.java
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
calls++;
// Call the next interceptor in the chain.
// 注释1 index 最开始等于零 每次new 都加1
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
// 注释 2 核心代码
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
return response;
}
这里就是 getResponseWithInterceptorChain
执行的核心代码位置,也是OkHttp 拦截器设计的精妙之处, 每次都创建一个 Chain
然后把Chain
丢着拦截器执行intercept
, 然后在拦截器中执行 Chain
的proceed
。 比如我们随便找一个 拦截器。
public final class ConnectInterceptor implements Interceptor {
public final OkHttpClient client;
public ConnectInterceptor(OkHttpClient client) {
this.client = client;
}
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
}
显然这里验证了上面的猜想, 没个拦截器中都加入了一些自己对于 网络请求的判断逻辑, 每个拦截器各司其职完成自己功能。 比如 retryAndFollowUpInterceptor
负责重试相关的操作,ConnectInterceptor
负责链接相关的 操作。一直到执行最后一个操作 CallServerInterceptor
这里是真正请求网络服务器的操作。
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
HttpCodec httpCodec = realChain.httpStream();
StreamAllocation streamAllocation = realChain.streamAllocation();
RealConnection connection = (RealConnection) realChain.connection();
Request request = realChain.request();
long sentRequestMillis = System.currentTimeMillis();
realChain.eventListener().requestHeadersStart(realChain.call());
httpCodec.writeRequestHeaders(request);
realChain.eventListener().requestHeadersEnd(realChain.call(), request);
Response.Builder responseBuilder = null;
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
// Expect:100-continue, 询问Server使用愿意接受数据
httpCodec.flushRequest();
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(true);
}
if (responseBuilder == null) {
// Write the request body if the "Expect: 100-continue" expectation was met.
realChain.eventListener().requestBodyStart(realChain.call());
long contentLength = request.body().contentLength();
//
CountingSink requestBodyOut =
new CountingSink(httpCodec.createRequestBody(request, contentLength));
// 调用Okio 然后把request请求 得到一个BufferedSink 输出流
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
//将请求都写到 buffer里面,这buffer就在request身上
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
realChain.eventListener()
.requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
} else if (!connection.isMultiplexed()) {
streamAllocation.noNewStreams();
}
}
httpCodec.finishRequest();
if (responseBuilder == null) {
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(false);
}
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
// 后面的代码基本可以不看
int code = response.code();
if (code == 100) {
// server sent a 100-continue even though we did not request one.
// try again to read the actual response
responseBuilder = httpCodec.readResponseHeaders(false);
response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
code = response.code();
}
realChain.eventListener()
.responseHeadersEnd(realChain.call(), response);
if (forWebSocket && code == 101) {
// Connection is upgrading, but we need to ensure interceptors see a non-null response body.
response = response.newBuilder()
.body(Util.EMPTY_RESPONSE)
.build();
} else {
response = response.newBuilder()
.body(httpCodec.openResponseBody(response))
.build();
}
// 省略一部分代码
return response;
}
综上的分析这里做的操作就是 调用okio发送出请求信息,然后这个信息就被封装成了一个Response 对象, 但是这个Response
并不是一个实际的结果, 应为实际的结果是在一个buffer
中,最后我们会得到 ResponseBody
。 这也是为甚ResponseBody.string()
只能执行一次的原因,因为数据实在一个buffer里面,读一次就就colse
了。