以get請(qǐng)求為例子:
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url("").build();
Response response=client.newCall(request).execute();
三行代碼就可以創(chuàng)建一個(gè)請(qǐng)求 , 接下來(lái)我們查看具體的代碼
OkHttpClient client=new OkHttpClient();
public OkHttpClient() {
this(new Builder());
}
構(gòu)造方法中再次調(diào)用有參的構(gòu)造方法 , 點(diǎn)進(jìn)去之后 , 會(huì)發(fā)現(xiàn)一系列的初始化操作 . 其中我們關(guān)心這幾個(gè)屬性 , 先記住名字就好
- dispatcher 分發(fā)器
- interceptors 應(yīng)用層的攔截器
- networkInterceptors 網(wǎng)絡(luò)層攔截器
Request request=new Request.Builder().url("").build();
其實(shí)這里就是一個(gè)對(duì)象的初始化過(guò)程.......不多解釋了
Response response=client.newCall(request).execute();
從newCall()方法開(kāi)始:
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
直接實(shí)例化了另一個(gè)類(lèi)RealCall, 實(shí)例化之后 , 回到原來(lái)的語(yǔ)句中 , 接下來(lái)執(zhí)行的execute()方法 , 就肯定是在該類(lèi)中進(jìn)行的了
這里不要直接點(diǎn)擊execute , 會(huì)跑偏的= =
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
// 使用分發(fā)器來(lái)處理
client.dispatcher().executed(this);
// 交由攔截器來(lái)處理
Response result = getResponseWithInterceptorChain(false);
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
這里主要有兩個(gè)方法 , 一個(gè)分發(fā) , 一個(gè)攔截. 我們先看分發(fā)器的executed的實(shí)現(xiàn):
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
恩.......比較簡(jiǎn)單昂 , 就是將請(qǐng)求添加到隊(duì)列中 , 這里用到隊(duì)列數(shù)據(jù)結(jié)構(gòu). 加入隊(duì)列之后, 攔截器來(lái)進(jìn)一步處理
private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {
Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);
return chain.proceed(originalRequest);
}
首先創(chuàng)建了一個(gè)應(yīng)用層的攔截器ApplicationInterceptorChain , 再調(diào)用攔截器的proceed方法 , 獲取到請(qǐng)求數(shù)據(jù).
先點(diǎn)開(kāi)ApplicationInterceptorChain , 發(fā)現(xiàn)它是一個(gè)內(nèi)部類(lèi) , 初始化了一些東西 , 然后接下來(lái)的proceed方法也應(yīng)該在這個(gè)類(lèi)里面了
@Override public Response proceed(Request request) throws IOException {
// If there's another interceptor in the chain, call that.
if (index < client.interceptors().size()) {
Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket);
Interceptor interceptor = client.interceptors().get(index);
Response interceptedResponse = interceptor.intercept(chain);
if (interceptedResponse == null) {
throw new NullPointerException("application interceptor " + interceptor
+ " returned null");
}
return interceptedResponse;
}
// No more interceptors. Do HTTP.
// 開(kāi)始請(qǐng)求
return getResponse(request, forWebSocket);
}
}
這里先判斷了當(dāng)前攔截器有沒(méi)有對(duì)應(yīng)的處理 , 沒(méi)有就新建一個(gè)攔截器 , 并執(zhí)行intercept方法 . 攔截器可以用來(lái)轉(zhuǎn)換格式 , 重寫(xiě)請(qǐng)求等......最后 , 反回了真正的請(qǐng)求getResponse()
Response getResponse(Request request, boolean forWebSocket) throws IOException {
// Copy body metadata to the appropriate request headers.
RequestBody body = request.body();
// 拼接請(qǐng)求頭
if (body != null) {
Request.Builder requestBuilder = request.newBuilder();
MediaType contentType = body.contentType();
if (contentType != null) {
requestBuilder.header("Content-Type", contentType.toString());
}
long contentLength = body.contentLength();
if (contentLength != -1) {
requestBuilder.header("Content-Length", Long.toString(contentLength));
requestBuilder.removeHeader("Transfer-Encoding");
} else {
requestBuilder.header("Transfer-Encoding", "chunked");
requestBuilder.removeHeader("Content-Length");
}
request = requestBuilder.build();
}
// Create the initial HTTP engine. Retries and redirects need new engine for each attempt.
// 創(chuàng)建HTTP engine, 用于發(fā)送和回復(fù)的細(xì)節(jié)處理
engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null);
int followUpCount = 0;
while (true) {
if (canceled) {
engine.releaseStreamAllocation();
throw new IOException("Canceled");
}
boolean releaseConnection = true;
try {
// 發(fā)送請(qǐng)求
engine.sendRequest();
// 讀取回復(fù)
engine.readResponse();
releaseConnection = false;
} catch (RequestException e) {
// The attempt to interpret the request failed. Give up.
throw e.getCause();
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
HttpEngine retryEngine = engine.recover(e.getLastConnectException(), true, null);
if (retryEngine != null) {
releaseConnection = false;
engine = retryEngine;
continue;
}
// Give up; recovery is not possible.
throw e.getLastConnectException();
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
HttpEngine retryEngine = engine.recover(e, false, null);
if (retryEngine != null) {
releaseConnection = false;
engine = retryEngine;
continue;
}
// Give up; recovery is not possible.
throw e;
} finally {
// We're throwing an unchecked exception. Release any resources.
if (releaseConnection) {
StreamAllocation streamAllocation = engine.close();
streamAllocation.release();
}
}
Response response = engine.getResponse();
Request followUp = engine.followUpRequest();
if (followUp == null) {
if (!forWebSocket) {
engine.releaseStreamAllocation();
}
return response;
}
StreamAllocation streamAllocation = engine.close();
if (++followUpCount > MAX_FOLLOW_UPS) {
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (!engine.sameConnection(followUp.url())) {
streamAllocation.release();
streamAllocation = null;
} else if (streamAllocation.stream() != null) {
throw new IllegalStateException("Closing the body of " + response
+ " didn't close its backing stream. Bad interceptor?");
}
request = followUp;
engine = new HttpEngine(client, request, false, false, forWebSocket, streamAllocation, null,
response);
}
}
首先 , 設(shè)置請(qǐng)求頭 , 拼接一條完整的請(qǐng)求, 然后初始化HttpEngine用于細(xì)節(jié)優(yōu)化 , 再開(kāi)始請(qǐng)求 , 請(qǐng)求完成后讀取請(qǐng)求結(jié)果.
- 開(kāi)始請(qǐng)求部分:
public void sendRequest() throws RequestException, RouteException, IOException {
if (cacheStrategy != null) return; // Already sent.
if (httpStream != null) throw new IllegalStateException();
// 首先 ,對(duì)請(qǐng)求頭再次做一次處理
Request request = networkRequest(userRequest);
// 獲取用戶(hù)設(shè)置的緩存
InternalCache responseCache = Internal.instance.internalCache(client);
// 從緩存中獲取之前請(qǐng)求過(guò)的Response
Response cacheCandidate = responseCache != null
? responseCache.get(request)
: null;
long now = System.currentTimeMillis();
// 根據(jù)請(qǐng)求和緩存結(jié)果來(lái)設(shè)置緩存策略,先從緩存拿,如果超時(shí),那么從網(wǎng)絡(luò)請(qǐng)求.
cacheStrategy = new CacheStrategy.Factory(now, request, cacheCandidate).get();
networkRequest = cacheStrategy.networkRequest;
cacheResponse = cacheStrategy.cacheResponse;
if (responseCache != null) {
responseCache.trackResponse(cacheStrategy);
}
if (cacheCandidate != null && cacheResponse == null) {
closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
}
...
...
try {
// 建立鏈接, 使用socket創(chuàng)建,可以自動(dòng)選擇偏好鏈接, 選擇連接時(shí),首先從連接池來(lái)查找,
// 沒(méi)有的話(huà)使用路徑選擇器,若還找不到的話(huà)就新建一個(gè)連接,同時(shí)將連接放到連接池中
httpStream = connect();
httpStream.setHttpEngine(this);
if (writeRequestHeadersEagerly()) {
long contentLength = OkHeaders.contentLength(request);
if (bufferRequestBody) {
if (contentLength > Integer.MAX_VALUE) {
throw new IllegalStateException("Use setFixedLengthStreamingMode() or "
+ "setChunkedStreamingMode() for requests larger than 2 GiB.");
}
if (contentLength != -1) {
// Buffer a request body of a known length.
httpStream.writeRequestHeaders(networkRequest);
requestBodyOut = new RetryableSink((int) contentLength);
} else {
// Buffer a request body of an unknown length. Don't write request headers until the
// entire body is ready; otherwise we can't set the Content-Length header correctly.
requestBodyOut = new RetryableSink();
}
} else {
httpStream.writeRequestHeaders(networkRequest);
requestBodyOut = httpStream.createRequestBody(networkRequest, contentLength);
}
}
success = true;
} finally {
// If we're crashing on I/O or otherwise, don't leak the cache body.
if (!success && cacheCandidate != null) {
closeQuietly(cacheCandidate.body());
}
}