原始碼解析一次OKHttp請求的過程
ofollow,noindex">OkHttp 這個庫有多優秀作為Androider大家心裡都明白,應該說合格的開發者都認識它。那麼,這裡簡單看個OKHttp的介面請求姿勢:
OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url("https://www.xxxx.com/xxx/xxx/xxx") .build(); Call call = okHttpClient.newCall(request); //開始執行非同步介面請求 call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 這裡介面請求失敗 } @Override public void onResponse(Call call, Response response) throws IOException { // 這裡介面請求成功 } });
所以很明顯了弄懂了上面幾個類的是幹嘛、上個幾個流程做了什麼自然就明白了OKHttp的執行流程了,那麼就開始分析吧。
OKHttp請求中需要的物件
Request
這個類是典型的'Builder'設計模式,看一眼他的成員屬性就知道這個類是幹嘛的了。
public final class Request { final HttpUrl url; final String method; final Headers headers; final @Nullable RequestBody body; final Object tag; . . . }
看看變數名就知道了這個類封裝那些玩意,還是很愉快的完成了一小步。
OkHttpClient
這個類類似個Manager類,裡面的成員屬性自然也比較多了。
我們重點關注Dispatcher這個執行緒池屬性:
// 可以傳入執行緒池,從而自定義OKHttp執行緒池 public Dispatcher(ExecutorService executorService) { this.executorService = executorService; } public Dispatcher() { } // 初始化執行緒池 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; }
所以 Dispatcher
就是一個執行緒池管理類,用於分發每一次的Http請求。
Call
是介面真正的實現類是 RealCall
,而 RealCall
有個內部類叫 AsyncCall
是個介面,最終加入 Dispatcher
執行緒池的就是 AsyncCall
物件。
執行Http請求操作
我們從okHttpClient.newCall操作開始閱讀:
/** * Prepares the {@code request} to be executed at some point in the future. */ @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)); }
再看最後一行程式碼會執行 Dispatcher.enqueue
方法,同樣的進入看看程式碼怎麼執行的:
synchronized void enqueue(AsyncCall call) { if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { runningAsyncCalls.add(call); executorService().execute(call); } else { readyAsyncCalls.add(call); } }
由於 AsyncCall
是實現了 NamedRunnable
介面,所以執行緒池就會執行 NamedRunnable.run
方法,這樣子自然就執行到 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); } } }
我們可以看到這裡直接通過getResponseWithInterceptorChain()方法直接得到Response然後通過Callback回撥資料回去。
攔截器Interceptor
通過上面我們知道已經得到Response基本上可以說已經結束了一個流程,這裡並不細節的解釋每個攔截器的程式碼,只是介紹一下攔截器的呼叫時序,所以仍然先看一下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 (!forSocket/">WebSocket) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor(forWebSocket)); Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest); }
我們可以看到系統已經為我們定義幾個預設的攔截器,他們的作用一起呼叫時序如下:

WechatIMG61.png
這裡知道了呼叫時序,那從什麼時候觸發呼叫?
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest);
我們可以看到是先封裝一個RealInterceptorChain物件,然後執行proceed方法自然就會執行每一個interceptor.intercept方法。OKHttp的所有精髓之一就是攔截器的使用..
最後,這裡我們也可以明白一點addInterceptor / addNetworkInterceptor兩者之間有何不同了,因為他們倆的呼叫時序不一樣。
更多攔截器的分析,將在未來找時間分析。