記錄以okhttp 版本號為 3.14.9 的請求為例坚踩,看源碼執(zhí)行一個請求的基本流程
開始使用
String url = "http://wwww.baidu.com";
final Request request = new Request.Builder()
.url(url)
.build();
OkHttpClient okHttpClient=new OkHttpClient();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(getClass().getSimpleName(), "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(getClass().getSimpleName(), "onResponse: " + response.code());
}
});
從 call.enqueue 開始 ctrl +鼠標(biāo)左擊可以看到Call是個接口,主要執(zhí)行類為RealCall類的enqueue方法槽唾,
public void enqueue(Callback responseCallback) {
synchronized(this) {
if (this.executed) {
throw new IllegalStateException("Already Executed");
}
this.executed = true;
}
this.transmitter.callStart();
this.client.dispatcher().enqueue(new RealCall.AsyncCall(responseCallback));
}
根據(jù)上面代碼可以看到 enqueue函數(shù)里new RealCall里的內(nèi)部類AsyncCall對象,而AsyncCall是一個繼承了NamedRunnable類伐谈,NamedRunnable實現(xiàn)了runable 接口的實現(xiàn)類医吊,并且NamedRunnable類的run方法調(diào)用execute()方法焕议,如下代碼所示
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(this.name);
try {
this.execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
再看看AsyncCall類的execute()方法挠日,可以從下面看到請求的結(jié)果從getResponseWithInterceptorChain方法中獲取到疮绷。
protected void execute() {
boolean signalledCallback = false;
RealCall.this.transmitter.timeoutEnter();
try {
//請求結(jié)束獲取到請求結(jié)果
Response response = RealCall.this.getResponseWithInterceptorChain();
signalledCallback = true;
this.responseCallback.onResponse(RealCall.this, response);
} catch (IOException var8) {
if (signalledCallback) {
Platform.get().log(4, "Callback failure for " + RealCall.this.toLoggableString(), var8);
} else {
this.responseCallback.onFailure(RealCall.this, var8);
}
} catch (Throwable var9) {
RealCall.this.cancel();
if (!signalledCallback) {
IOException canceledException = new IOException("canceled due to " + var9);
canceledException.addSuppressed(var9);
this.responseCallback.onFailure(RealCall.this, canceledException);
}
throw var9;
} finally {
RealCall.this.client.dispatcher().finished(this);
}
}
從下面代碼可以看到getResponseWithInterceptorChain方法主要就是添加多個攔截器,并放入攔截器數(shù)組中嚣潜。
下一步就是創(chuàng)建個攔截鏈類RealInterceptorChain 冬骚,并調(diào)用攔截鏈的proceed方法,
Response getResponseWithInterceptorChain() throws IOException {
List<Interceptor> interceptors = new ArrayList();
interceptors.addAll(this.client.interceptors());
interceptors.add(new RetryAndFollowUpInterceptor(this.client));
interceptors.add(new BridgeInterceptor(this.client.cookieJar()));
interceptors.add(new CacheInterceptor(this.client.internalCache()));
interceptors.add(new ConnectInterceptor(this.client));
if (!this.forWebSocket) {
interceptors.addAll(this.client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(this.forWebSocket));
Chain chain = new RealInterceptorChain(interceptors, this.transmitter, (Exchange)null, 0, this.originalRequest, this, this.client.connectTimeoutMillis(), this.client.readTimeoutMillis(), this.client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
Response var5;
try {
Response response = chain.proceed(this.originalRequest);
if (this.transmitter.isCanceled()) {
Util.closeQuietly(response);
throw new IOException("Canceled");
}
var5 = response;
} catch (IOException var9) {
calledNoMoreExchanges = true;
throw this.transmitter.noMoreExchanges(var9);
} finally {
if (!calledNoMoreExchanges) {
this.transmitter.noMoreExchanges((IOException)null);
}
}
return var5;
}
從下面代碼proceed方法里的操作主要就是把攔截器數(shù)組里的攔截器從第一個攔截器開始懂算,調(diào)用攔截器的intercept方法只冻,傳入的參數(shù)為RealInterceptorChain 類本身的對象。由RealCall類的getResponseWithInterceptorChain方法可知第一個攔截器為RetryAndFollowUpInterceptor 计技。
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange) throws IOException {
if (this.index >= this.interceptors.size()) {
throw new AssertionError();
} else {
++this.calls;
if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must retain the same host and port");
} else if (this.exchange != null && this.calls > 1) {
throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must call proceed() exactly once");
} else {
RealInterceptorChain next = new RealInterceptorChain(this.interceptors, transmitter, exchange, this.index + 1, request, this.call, this.connectTimeout, this.readTimeout, this.writeTimeout);//傳入類本身的對象
Interceptor interceptor = (Interceptor)this.interceptors.get(this.index);
Response response = interceptor.intercept(next);
if (exchange != null && this.index + 1 < this.interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor + " must call proceed() exactly once");
} else if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
} else if (response.body() == null) {
throw new IllegalStateException("interceptor " + interceptor + " returned a response with no body");
} else {
return response;
}
}
}
}
從下面代碼RetryAndFollowUpInterceptor類的intercept方法喜德,做好本身的業(yè)務(wù)處理后,在調(diào)用RealInterceptorChain的proceed方法垮媒,如此流程調(diào)用完攔截器數(shù)組的每一個攔截器類舍悯。 請求服務(wù)器的鏈接攔截器類CallServerInterceptor,有命名名稱可知為鏈接攔截器涣澡,主要進(jìn)行與服務(wù)器之間的請求鏈接
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain)chain;
Transmitter transmitter = realChain.transmitter();
int followUpCount = 0;
Response priorResponse = null;
while(true) {
transmitter.prepareToConnect(request);
if (transmitter.isCanceled()) {
throw new IOException("Canceled");
}
boolean success = false;
Response response;
try {
//調(diào)用傳入的Chain類的proceed方法贱呐,即攔截器鏈的對象
response = realChain.proceed(request, transmitter, (Exchange)null);
success = true;
} catch (RouteException var16) {
if (this.recover(var16.getLastConnectException(), transmitter, false, request)) {
continue;
}
throw var16.getFirstConnectException();
} catch (IOException var17) {
boolean requestSendStarted = !(var17 instanceof ConnectionShutdownException);
if (!this.recover(var17, transmitter, requestSendStarted, request)) {
throw var17;
}
continue;
} finally {
if (!success) {
transmitter.exchangeDoneDueToException();
}
}
if (priorResponse != null) {
response = response.newBuilder().priorResponse(priorResponse.newBuilder().body((ResponseBody)null).build()).build();
}
Exchange exchange = Internal.instance.exchange(response);
Route route = exchange != null ? exchange.connection().route() : null;
Request followUp = this.followUpRequest(response, route);
if (followUp == null) {
if (exchange != null && exchange.isDuplex()) {
transmitter.timeoutEarlyExit();
}
return response;
}
RequestBody followUpBody = followUp.body();
if (followUpBody != null && followUpBody.isOneShot()) {
return response;
}
Util.closeQuietly(response.body());
if (transmitter.hasExchange()) {
exchange.detachWithViolence();
}
++followUpCount;
if (followUpCount > 20) {
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
request = followUp;
priorResponse = response;
}
}
從下面CallServerInterceptor類的CallServerInterceptor方法中可以看到丧诺,該類主要做一下幾方面處理
- requestHeader 請求頭處理
- RequestBody 請求體處理
- 后臺返回responseHeader響應(yīng)頭處理
- 后臺返回responseBody響應(yīng)體處理
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain)chain;
Exchange exchange = realChain.exchange();
Request request = realChain.request();
long sentRequestMillis = System.currentTimeMillis();
exchange.writeRequestHeaders(request);
boolean responseHeadersStarted = false;
Builder responseBuilder = null;
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
exchange.flushRequest();
responseHeadersStarted = true;
exchange.responseHeadersStart();
responseBuilder = exchange.readResponseHeaders(true);
}
if (responseBuilder == null) {
BufferedSink bufferedRequestBody;
if (request.body().isDuplex()) {
exchange.flushRequest();
bufferedRequestBody = Okio.buffer(exchange.createRequestBody(request, true));
request.body().writeTo(bufferedRequestBody);
} else {
bufferedRequestBody = Okio.buffer(exchange.createRequestBody(request, false));
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
}
} else {
exchange.noRequestBody();
if (!exchange.connection().isMultiplexed()) {
exchange.noNewExchangesOnConnection();
}
}
} else {
exchange.noRequestBody();
}
if (request.body() == null || !request.body().isDuplex()) {
exchange.finishRequest();
}
if (!responseHeadersStarted) {
exchange.responseHeadersStart();
}
if (responseBuilder == null) {
responseBuilder = exchange.readResponseHeaders(false);
}
Response response = responseBuilder.request(request).handshake(exchange.connection().handshake()).sentRequestAtMillis(sentRequestMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
int code = response.code();
if (code == 100) {
response = exchange.readResponseHeaders(false).request(request).handshake(exchange.connection().handshake()).sentRequestAtMillis(sentRequestMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
code = response.code();
}
exchange.responseHeadersEnd(response);
if (this.forWebSocket && code == 101) {
response = response.newBuilder().body(Util.EMPTY_RESPONSE).build();
} else {
response = response.newBuilder().body(exchange.openResponseBody(response)).build();
}
if ("close".equalsIgnoreCase(response.request().header("Connection")) || "close".equalsIgnoreCase(response.header("Connection"))) {
exchange.noNewExchangesOnConnection();
}
if ((code == 204 || code == 205) && response.body().contentLength() > 0L) {
throw new ProtocolException("HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
} else {
return response;
}
}