OkHttp解析

今天花了一天時間研究了下OkHttp3的內部原理,記錄在此處以便後期查閱web

咱們先來看下基本的使用方式:緩存

 1  public  void sendHttpRequest(String url,Callback callback){
 2         OkHttpClient client=new OkHttpClient();
 3         Request request=new Request.Builder().url(url).build();
 4         client.newCall(request).enqueue(callback); //異步執行
 5         try {
 6             client.newCall(request).execute();//同步執行
 7         } catch (IOException e) {
 8             e.printStackTrace();
 9         }
10     }

接下來的分析就以異步執行開始cookie

1  @Override
2 public Call newCall(Request request) {
3     return new RealCall(this, request, false /* for web socket */);
4 }
1   RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
2     this.client = client;
3     this.originalRequest = originalRequest;
4     this.forWebSocket = forWebSocket;
5     this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
6   }

  RealCall的enqueue()方法網絡

1   @Override public void enqueue(Callback responseCallback) {
2     synchronized (this) {
3       if (executed) throw new IllegalStateException("Already Executed");
4       executed = true;
5     }
6     captureCallStackTrace();
7     client.dispatcher().enqueue(new AsyncCall(responseCallback));
8   }

  

1  synchronized void enqueue(AsyncCall call) {
2     if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {//同時發起的請求不能超過最大請求數,若是超過了,就放入readyAsyncCalls隊列
3       runningAsyncCalls.add(call);
4       executorService().execute(call);
5     } else {
6       readyAsyncCalls.add(call);
7     }
8   }

  線程池異步

1   public synchronized ExecutorService executorService() {
2     if (executorService == null) {
3       executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
4           new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
5     }
6     return executorService;
7   }

  執行AsyncCall 的run方法 ,在父類 NamedRunnable 中socket

 @Override public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();//由子類實現
 1   @Override protected void execute() {
 2       boolean signalledCallback = false;
 3       try {
 4         Response response = getResponseWithInterceptorChain();//重點查看
 5         if (retryAndFollowUpInterceptor.isCanceled()) {
 6           signalledCallback = true;
 7           responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
 8         } else {
 9           signalledCallback = true;
10           responseCallback.onResponse(RealCall.this, response);
11         }
12       } catch (IOException e) {
13         if (signalledCallback) {
14           // Do not signal the callback twice!
15           Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
16         } else {
17           responseCallback.onFailure(RealCall.this, e);
18         }
19       } finally {
20         client.dispatcher().finished(this);
21       }
22     }

  如今咱們進入 getResponseWithInterceptorChain() 方法查看ide

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); 
  }
 1   public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
 2       Connection connection) throws IOException {
 3  //........
 4     RealInterceptorChain next = new RealInterceptorChain(
 5         interceptors, streamAllocation, httpCodec, connection, index + 1, request);
 6     Interceptor interceptor = interceptors.get(index);
 7     Response response = interceptor.intercept(next); //攔截器中都會調用 chain.proceed(request)來獲取response,產生遞歸,依次調用各個攔截器的intercept方法
 8 
 9  //.........
10 
11     return response;
12   }

  其餘攔截器就不看了,咱們來看看比較重要的緩存攔截器ui

  

 1   @Override public Response intercept(Chain chain) throws IOException {
 2     Response cacheCandidate = cache != null
 3         ? cache.get(chain.request())
 4         : null;//查看是否有緩存
 5 
 6     CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();//根據緩存響應頭返回的一些信息來制定緩存策略,是從緩存取仍是從網絡上取
 7     Request networkRequest = strategy.networkRequest;
 8     Response cacheResponse = strategy.cacheResponse;
 9 
10    //..............
11 
12     // If we're forbidden from using the network and the cache is insufficient, fail. 禁止使用網絡而且緩存也是空的,請求失敗
13     if (networkRequest == null && cacheResponse == null) {
14       return new Response.Builder()
15           .request(chain.request())
16           .protocol(Protocol.HTTP_1_1)
17           .code(504)
18           .message("Unsatisfiable Request (only-if-cached)")
19           .body(Util.EMPTY_RESPONSE)
20           .sentRequestAtMillis(-1L)
21           .receivedResponseAtMillis(System.currentTimeMillis())
22           .build();
23     }
24 
25     // If we don't need the network, we're done. 若是不須要網絡,直接返回緩存
26     if (networkRequest == null) {
27       return cacheResponse.newBuilder()
28           .cacheResponse(stripBody(cacheResponse))
29           .build();
30     }
31 
32     Response networkResponse = null;
33     try {
34       networkResponse = chain.proceed(networkRequest);
35     } finally {
36       // If we're crashing on I/O or otherwise, don't leak the cache body.
37       if (networkResponse == null && cacheCandidate != null) {
38         closeQuietly(cacheCandidate.body());
39       }
40     }
41 
42     // If we have a cache response too, then we're doing a conditional get.
43     if (cacheResponse != null) {
44       if (networkResponse.code() == HTTP_NOT_MODIFIED) {
45         Response response = cacheResponse.newBuilder()
46             .headers(combine(cacheResponse.headers(), networkResponse.headers()))
47             .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
48             .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
49             .cacheResponse(stripBody(cacheResponse))
50             .networkResponse(stripBody(networkResponse))
51             .build();
52         networkResponse.body().close();
53 
54         // Update the cache after combining headers but before stripping the
55         // Content-Encoding header (as performed by initContentStream()).
56         cache.update(cacheResponse, response); //更新緩存
57         return response;
58       } else {
59         closeQuietly(cacheResponse.body());
60       }
61     }
62 
63     Response response = networkResponse.newBuilder()
64         .cacheResponse(stripBody(cacheResponse))
65         .networkResponse(stripBody(networkResponse))
66         .build();
67 
68     if (HttpHeaders.hasBody(response)) {
69       CacheRequest cacheRequest = maybeCache(response, networkResponse.request(), cache);
70       response = cacheWritingResponse(cacheRequest, response);
71     }
72 
73     return response;
74   }

太暈了,來張圖看看吧this

相關文章
相關標籤/搜索