okhttp使用分為同步請求和異步請求:
異步請求:
String url = "";
Request request = new Request.Builder().get().url(url).build();
OkHttpClient okHttpClient = new OkHttpClient();
public void request(){
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
request是一個請求對像堪置,包含了請求url躬存,methord,heard等信息
okhttpclient 主要用于發(fā)送http請求以及讀取回應
newcall方法主要是用于返回一個realcall對象舀锨,并且把請求對象request交給了realcall
@Override public Call newCall(Request request) {
return new RealCall(this, request, false /* for web socket */);
}
接下來看一下realcall的enqueue
方法:
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
首先通過同步岭洲,確保call不會被重復執(zhí)行(如果想要完全相同的call可以通過clone
方法),然后利用dispatcher
調(diào)度器來執(zhí)行enqueue
方法坎匿,下面看一下dispatcher.enqueue
方法:
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
dispatcher就是一個異步請求是的策略盾剩,它里面包含了能同時進行的最大請求數(shù)(默認是64),同時請求相同host的最大數(shù)(默認是5)替蔬,以及維護一個異步任務執(zhí)行隊列和一個異步任務等待隊列告私,然后回來看dispatcher.enqueue
方法,首先會判斷當前執(zhí)行隊列是不是超出最大請求數(shù)进栽,以及同時訪問相同host的數(shù)量是不是超過德挣,如果超過就將call放入等待隊列恭垦,否則放入執(zhí)行隊列快毛,并且交給線程池去執(zhí)行
執(zhí)行的為AsyncCall,我們看一下AsyncCall的實現(xiàn):
final class AsyncCall extends NamedRunnable {
AsyncCall繼承自NamedRunnable番挺,NamedRunnable其實是繼承自Runnable唠帝,在他的run方法中會調(diào)用execute();
方法,說到底其實就是會執(zhí)行AsyncCall的execute();
方法玄柏,接下來看一下AsyncCall的execute();
方法:
@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);
}
}
可以看到真正執(zhí)行請求的是getResponseWithInterceptorChain()
,獲取到response后回調(diào)給用戶襟衰,值得注意的是最后finally,會通過調(diào)度器移除隊列粪摘,并且判斷如果執(zhí)行隊列沒有達到最大值則把等待隊列變?yōu)閳?zhí)行隊列瀑晒,這樣就包證了等待隊列的執(zhí)行
下面我們看一下真正請求的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);
return chain.proceed(originalRequest);
}
我們可以看到方法中首先創(chuàng)建一個攔截器的列表,添加各個攔截器徘意,每個攔截器個自完成自己的任務苔悦,并且將不屬于自己的任務交給下一個,這就是一種責任鏈模式椎咧,最后的執(zhí)行是由chain.proceed(originalRequest);
來實現(xiàn)的玖详,責任鏈中每個攔截器都會執(zhí)行chain.proceed()方法之前的代碼,等責任鏈最后一個攔截器執(zhí)行完畢后會返回最終的響應數(shù)據(jù),而chain.proceed() 方法會得到最終的響應數(shù)據(jù)蟋座,這時就會執(zhí)行每個攔截器的chain.proceed()方法之后的代碼拗踢,其實就是對響應數(shù)據(jù)的一些操作。
@Override public Response proceed(Request request) throws IOException {
return proceed(request, streamAllocation, httpCodec, connection);
}
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");
}
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpCodec, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// 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");
}
return response;
}
簡述okhttp的執(zhí)行流程:
- OkhttpClient 實現(xiàn)了Call.Fctory,負責為Request 創(chuàng)建 Call向臀;
- RealCall 為Call的具體實現(xiàn)巢墅,其enqueue() 異步請求接口通過Dispatcher()調(diào)度器利用ExcutorService實現(xiàn),而最終進行網(wǎng)絡請求時和同步的execute()接口一致飒硅,都是通過 getResponseWithInterceptorChain() 函數(shù)實現(xiàn)
- getResponseWithInterceptorChain() 中利用 Interceptor 鏈條砂缩,責任鏈模式 分層實現(xiàn)緩存、透明壓縮三娩、網(wǎng)絡 IO 等功能庵芭;最終將響應數(shù)據(jù)返回給用戶。