攔截器詳細解析可以看大佬簡書 "https://www.jianshu.com/p/6fac73f7570f"和 “https://www.jianshu.com/p/3c740829475c”
okhttp請求流程
1:OkHttpClient okHttpClient = new OkHttpClient.Builder()
構建一個okhttpClient對象,傳入你想傳入的對象,不傳就是默認的;
2:構建request對象
Request request = new Request.Builder()
3:okHttpClient.newCall 實際上返回的realCall類 繼續調用RealCall.newRealCall
4:調用enqueue方法,傳入我們需要的回調接口,而且會判斷,
synchronized (this) {
if (executed) throw new IllegalStateException(“Already Executed”);
executed = true;
}
如果當前這個call對象已經被運行的話,則拋出異常;
5:繼續調用dispatcher的enqueue方法,如果當前運行隊列<64并且正在運行,訪問同一個服務器地址的請求<5
就直接添加到運行隊列,并且開始運行;
不然就添加到等待隊列;
6:運行AsyncCall,調用它的execute方法
7:在execute方法中處理完response之后,會在finally中調用dispathcer的finished方法;
8:當當前已經處理完畢的call從運行隊列中移除掉;并且調用promoteCalls方法
9:promoteCalls方法中進行判斷,
如果運行隊列數目大于等于64,如果等待隊列里啥都沒有,也直接return?
循環等待隊列,
將等待隊列中的數據進行移除,移除是根據運行隊列中還能存放多少來決定;
移到了運行隊列中,并且開始運行;
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();Request request = new Request.Builder().build();//newCall方法是調用RealCall的newRealCall返回一個RealCallCall call = okHttpClient.newCall(request);//執行請求call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {}@Overridepublic void onResponse(Call call, Response response) throws IOException {}});//這里第二次執行會直接報IllegalStateException錯誤并提示Already Executedcall.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {}@Overridepublic void onResponse(Call call, Response response) throws IOException {}});
進入call.enqueue方法
@Override public void enqueue(Callback responseCallback) {//這個鎖是為了防止重復請求 如果你同一個call enqueue多次就會直接返回Already Executedsynchronized (this) {if (executed) throw new IllegalStateException("Already Executed");executed = true;}captureCallStackTrace();eventListener.callStart(this);//這里的enqueue是傳入任務線程AsyncCall并分配到運行隊列或等待隊列client.dispatcher().enqueue(new AsyncCall(responseCallback));}
進入enqueue方法
//okhttp里執行任務分為兩個隊列 運行隊列和等待隊列
synchronized void enqueue(AsyncCall call) {//當運行的隊列中的數值小于64, //并且同時訪問同一個機器目標HOST請求書小于5直接加入到運行隊列不然的話就加入到等待隊列if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {runningAsyncCalls.add(call);//這里維護著請求用的線程池executorService().execute(call);} else {readyAsyncCalls.add(call);}}
public synchronized ExecutorService executorService() {if (executorService == null) {//1:核心線程數 保持在線程池中的線程數量//2:線程池最大可容納的線程數 //3參數:當線程池中的線程數量大于核心線程數,空閑線程就會等待60s才會被終止,如果小于就會立刻停止;executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));}return executorService;}
//這個就是隊列中傳入的線程NameRunnable繼承自Runnable
final class AsyncCall extends NamedRunnable {private final Callback responseCallback;AsyncCall(Callback responseCallback) {super("OkHttp %s", redactedUrl());this.responseCallback = responseCallback;}String host() {return originalRequest.url().host();}Request request() {return originalRequest;}RealCall get() {return RealCall.this;}//這個就是Async的run方法@Override protected void execute() {boolean signalledCallback = false;try {//getResponseWithInterceptorChain() 添加攔截器 okhttp的責任鏈設計也在這里//response就是請求結果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 {eventListener.callFailed(RealCall.this, e);responseCallback.onFailure(RealCall.this, e);}} finally {//將執行完成的任務從隊列中移除client.dispatcher().finished(this);}}}
添加攔截器
//添加攔截器 責任鏈設計
//攔截器詳細解析可以看大佬簡書 "https://www.jianshu.com/p/6fac73f7570f"和 "https://www.jianshu.com/p/3c740829475c"
Response getResponseWithInterceptorChain() throws IOException {// Build a full stack of interceptors.List<Interceptor> interceptors = new ArrayList<>();interceptors.addAll(client.interceptors());//重試/重定向攔截器 連接失敗后進行重試、對請求結果跟進后進行重定向interceptors.add(retryAndFollowUpInterceptor);//橋攔截器:連接應用程序和服務器的橋梁,我們發出的請求會經過它的處理才能發給服務器,//比如設置請求內容的長度 封裝header屬性 host keep-live gzip header 進行基本設置,interceptors.add(new BridgeInterceptor(client.cookieJar()));//緩存攔截器 在發出請求前,先判斷是否命中緩存,//如果命中則可以不請求,直接使用緩存的響應(默認只會對Get請求進行緩存);//如果未命中則進行網絡請求,并將結果緩存,等待下次請求被命中。interceptors.add(new CacheInterceptor(client.internalCache()));//連接攔截器 與服務器建立連接。interceptors.add(new ConnectInterceptor(client));if (!forWebSocket) {interceptors.addAll(client.networkInterceptors());}//與服務器通信;封裝請求數據與解析響應數據(如:HTTP報文)。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);}
在execute方法中處理完response之后,會在finally中調用dispathcer的finished方法;
//將當前已經處理完畢的call從運行隊列中移除掉;并且調用promoteCalls方法
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {int runningCallsCount;Runnable idleCallback;synchronized (this) {if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");if (promoteCalls) promoteCalls();runningCallsCount = runningCallsCount();idleCallback = this.idleCallback;}if (runningCallsCount == 0 && idleCallback != null) {idleCallback.run();}}
promoteCalls方法中進行判斷
//如果運行隊列數目大于等于64,如果等待隊列里啥都沒有,也直接return
//循環等待隊列,
//將等待隊列中的數據進行移除,移除是根據運行隊列中還能存放多少來決定;
//移到了運行隊列中,并且開始運行;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();if (runningCallsForHost(call) < maxRequestsPerHost) {i.remove();runningAsyncCalls.add(call);executorService().execute(call);}if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.}}