OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
Request request = new Request.Builder()
.url(url)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i("response", "e:" + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i("response", "r:" + response.body().string());
}
});
/**
* 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 */);
}
进入RealCall发现这个方法就是 个静态方法,返回了一个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执行一个enquene的方法:
@Override
public void enqueue(Callback responseCallback) {
//不能重复执行
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//交给 dispatcher调度器 进行调度,也就是这里
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
直接看方法最后,这里Dispatcher登场了,又进入Dispatcher的enquene的方法,Dispatcher类的方法并不多,这里涉及点较多就全部贴出代码了,这里也不麻烦,我们依旧先不管其他的,只看关键执行的enquene方法,这里边使用executorService()这个其实就是一个线程一看便知。然后执行线程池的execute(call)方法,至此终于加入执行的队列了。接下来我们看这个参数call到底干了什么;
public final class Dispatcher {
private int maxRequests = 64;//最大请求数
private int maxRequestsPerHost = 5;//正在请求的队列(runningAsyncCalls)中,相同host的请求的最大数
private @Nullable
Runnable idleCallback;//Dispatcher闲置回调函数
/**
* 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<>();//见名知意 运行中的同步回调
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
public Dispatcher() {
}
public synchronized ExecutorService executorService() {
if (executorService == null) {
//TODO 线程池
//TODO 核心线程 最大线程 非核心线程闲置60秒回收 任务队列
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher",
false));
}
return executorService;
}
/**
* 设置最大并发线程数,超过这个数量的请求要等runningAsyncCalls中的请求执行完成
*/
public synchronized void setMaxRequests(int maxRequests) {
if (maxRequests < 1) {
throw new IllegalArgumentException("max < 1: " + maxRequests);
}
this.maxRequests = maxRequests;
promoteCalls();
}
public synchronized int getMaxRequests() {
return maxRequests;
}
/**
* 设置每个host请求的最大并发线程数,根据url的host来限制请求
*/
public synchronized void setMaxRequestsPerHost(int maxRequestsPerHost) {
if (maxRequestsPerHost < 1) {
throw new IllegalArgumentException("max < 1: " + maxRequestsPerHost);
}
this.maxRequestsPerHost = maxRequestsPerHost;
promoteCalls();
}
public synchronized int getMaxRequestsPerHost() {
return maxRequestsPerHost;
}
/**
* 设置闲置回调函数,当dispatcher闲置时的回调函数(running calls返回数量为0时回调)
* 请求闲置的时间根据执行的是同步请求还是异步请求有差异
* 异步请求在onResponse或onFailure回调后才闲置,同步请求一旦执行execute()就闲置。
*/
public synchronized void setIdleCallback(@Nullable Runnable idleCallback) {
this.idleCallback = idleCallback;
}
synchronized void enqueue(AsyncCall call) {
//同时请求不能超过并发数(64)
//这里 okhttp会使用共享主机即 地址相同的会共享socket
// 同一个host最多允许5条线程通知执行请求
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) <
maxRequestsPerHost) {
// 加入运行队列 并交给线程池执行
//AsyncCall 其实是一个runnable,查看其execute实现
runningAsyncCalls.add(call);
executorService().execute(call);//从这里开始执行
} else {
// 加入等候队列
readyAsyncCalls.add(call);
}
}
/**
* Cancel all calls currently enqueued or executing. Includes calls executed both {@linkplain
* Call#execute() synchronously} and {@linkplain Call#enqueue asynchronously}.
*/
public synchronized void cancelAll() {
for (AsyncCall call : readyAsyncCalls) {
call.get().cancel();
}
for (AsyncCall call : runningAsyncCalls) {
call.get().cancel();
}
for (RealCall call : runningSyncCalls) {
call.cancel();
}
}
private void promoteCalls() {
//检查 运行队列 与 等待队列
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
//相同host的请求没有达到最大
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
/**
* Returns the number of running calls that share a host with {@code call}.
*/
private int runningCallsForHost(AsyncCall call) {
int result = 0;
for (AsyncCall c : runningAsyncCalls) {
if (c.get().forWebSocket) continue;
if (c.host().equals(call.host())) result++;
}
return result;
}
/**
* Used by {@code Call#execute} to signal it is in-flight.
*/
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
/**
* Used by {@code AsyncCall#run} to signal completion.
*/
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
/**
* Used by {@code Call#execute} to signal completion.
*/
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
//TODO 移除队列
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
//TODO 检查执行 readyAsyncCalls 中的请求
if (promoteCalls) promoteCalls();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
//闲置调用
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
/**
* Returns a snapshot of the calls currently awaiting execution.
*/
public synchronized List<Call> queuedCalls() {
List<Call> result = new ArrayList<>();
for (AsyncCall asyncCall : readyAsyncCalls) {
result.add(asyncCall.get());
}
return Collections.unmodifiableList(result);
}
/**
* Returns a snapshot of the calls currently being executed.
*/
public synchronized List<Call> runningCalls() {
List<Call> result = new ArrayList<>();
result.addAll(runningSyncCalls);
for (AsyncCall asyncCall : runningAsyncCalls) {
result.add(asyncCall.get());
}
return Collections.unmodifiableList(result);
}
public synchronized int queuedCallsCount() {
return readyAsyncCalls.size();
}
public synchronized int runningCallsCount() {
return runningAsyncCalls.size() + runningSyncCalls.size();
}
}
call也就是AsynCall是RealCall中的一个内部类,继承自NamedRunnable,看名字也能猜到这个就是一个runnable的实现类,点击查看就是这样子,心里猜对了,这就是相当于丢到一个线程中执行了,那必然会走AsynCall的execute的方法,到这里算是有个大概的影子了,前面所有的那么多就是执行这个execute方法的; @Override
protected void execute() {
boolean signalledCallback = false;
try {
// 责任链模式
// 拦截器链 执行请求
Response response = getResponseWithInterceptorChain();
//回调结果 如果这里重定向取消了直接返回onfalile
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 {
//TODO 移除队列
client.dispatcher().finished(this);
}
}
}
仿佛看到了熟悉的onFaile ,onSuccess,对的没错,我们就是在这里获取到的response,然后进行处理之后,回调到当初使用的时候设置的CallBack的回调的.
到这里开始看拿这个response的。
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的一个集合,如果不算我们自定义插入的拦截器那这里就姑且算作5个。添加完成之后又new出一个RealInterceptorChain,这里就是一个拦截器看官方的介绍,就是一个拦截器约束链(姑且这么叫吧),
/**
* A concrete interceptor chain that carries the entire interceptor chain: all application
* interceptors, the OkHttp core, all network interceptors, and finally the network caller.
*/
看上一步 明显是最后走了proceed方法,我们看看这里执行又干了啥。
;
@Override
public Response proceed(Request request) throws IOException {
return proceed(request, streamAllocation, httpCodec, connection);
}
//明显这里最终调用了这个重载的proceed方法,这里的index与calls都是成员变量初始值为0
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;//这个只有正常执行的时候才会++,后面的判断也是为了防止多次执行该方法,所以直接抛出异常
// If we already have a stream, confirm that the incoming request will use it.
if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.httpCodec != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
//创建新的拦截链,链中的拦截器集合index+1
// Call the next interceptor in the chain.
****important****
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
//执行当前的拦截器 默认是第一个,也就是:retryAndFollowUpInterceptor
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
****important****
// Confirm that the next interceptor made its required call to chain.proceed().
if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
这里稍微有点绕,不过没关系,直接看重要部分。这里又new了一个拦截器链约束,但是跟第一次new的区别就是这个index+1了,我们接着看到从拦截器的集合中取了index=0(第一次执行的时候是0) ,也就是说执行了retryAndFollowUpInterceptor他的intercept(next)方法,我们进入这个类中查看。
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Call call = realChain.call();
EventListener eventListener = realChain.eventListener();
// 核心 协调连接、请求/响应以及复用
StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(request.url()), call, eventListener, callStackTrace);
this.streamAllocation = streamAllocation;
int followUpCount = 0;
Response priorResponse = null;
while (true) {
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}
Response response;
boolean releaseConnection = true;
try {
//TODO 执行责任链 实际上就是下一个拦截器
response = realChain.proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
throw e.getLastConnectException();
}
releaseConnection = false;
continue;
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
releaseConnection = false;
continue;
} finally {
// We're throwing an unchecked exception. Release any resources.
if (releaseConnection) {
streamAllocation.streamFailed(null);
streamAllocation.release();
}
}
// Attach the prior response if it exists. Such responses never have a body.
if (priorResponse != null) {
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}
Request followUp = followUpRequest(response, streamAllocation.route());
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
return response;
}
closeQuietly(response.body());
if (++followUpCount > MAX_FOLLOW_UPS) {
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (followUp.body() instanceof UnrepeatableRequestBody) {
streamAllocation.release();
throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
if (!sameConnection(response, followUp.url())) {
streamAllocation.release();
streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(followUp.url()), call, eventListener, callStackTrace);
this.streamAllocation = streamAllocation;
} else if (streamAllocation.codec() != null) {
throw new IllegalStateException("Closing the body of " + response
+ " didn't close its backing stream. Bad interceptor?");
}
request = followUp;
priorResponse = response;
}
}
好长,我们只简我们这波流程的,其他的先歇着不然流程都无法疏通。
这里先把chain转化为RealInterceptorChain,然后甩过几行,又看到了这个类执行了proceed方法,又回到了之前的拦截器链约束的类中的proceed方法,这个时候index是传入的因此index+1 =1了,这个时候就拿到了第二个拦截器BridgeInterceptor,这个看起来有点像是递归啊,其实这就是责任链,想想我们事件传递机制是不是也是差不多这种机制呢。按照这个节奏一直到第五个停止了,不再调用proceed方法了,代码为证。
@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 there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
// Continue" response before transmitting the request body. If we don't get that, return
// what we did get (such as a 4xx response) without ever transmitting the request body.
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
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));
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
realChain.eventListener()
.requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
} else if (!connection.isMultiplexed()) {
// If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
// from being reused. Otherwise we're still obligated to transmit the request body to
// leave the connection in a consistent state.
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();
}
if ("close".equalsIgnoreCase(response.request().header("Connection"))
|| "close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
throw new ProtocolException(
"HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
}
return response;
}
真没有了,而且我们看到了熟悉的写入操作,这不就是我们获取到的结果吗。至此大体上的网络请求的流程算是走完了。