OkHttp網絡請求框架源碼解析一

OkHttp網絡請求框架源碼解析一

 

 

基本使用,在app的build.gradle添加依賴

    compile 'com.squareup.okhttp3:okhttp:3.8.1'

在配置文件添加網絡訪問權限

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

具體使用流程:


//創建client
OkHttpClient client=new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();

//創建request        
final Request request=new Request.Builder().url("http://www.baidu.com").get().build();
        
//調用
Call call=client.newCall(request);
        
call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("fail",e.toString());
            }

            @Override
            public void onResponse(Call call, Response response) throws         IOException {
                Log.d("baidu:",response.body().string());
            }
        });

源碼分析:


//第一步:
OkHttpClient client=new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();

//其中Builder()方法,初始化一些默認參數,包括Dispatcher的創建,連接池的創建等。
public Builder() {

      //核心Dispatcher,call.enqueue()方法最終由dispatcher的enqueue()方法來完成請求。
      dispatcher = new Dispatcher();
      
      ......

      //連接池
      connectionPool = new ConnectionPool();

      ......      
    }

//其中build()方法,最終獲取OkHttpClient實例。典型的構建者模式。
public OkHttpClient build() {
      return new OkHttpClient(this);
    }


 

call.enqueue()方法


//最終調用RealCall裏面的enqueue
@Override public void enqueue(Callback responseCallback) {
    
    //鎖住RealCall對象
    synchronized (this) {
    
       //保證只請求一次 
     if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }

    //忽略非核心代碼
    ......
    
    //調用Dispatcher的enqueue方法 ,其中AsyncCall是Runnable。 
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }



 //調用Dispatcher的enqueue方法 ,其中AsyncCall是Runnable。  
synchronized void enqueue(AsyncCall call) {
    
//分別判斷正在執行的異步請求隊列大小 和 正在執行的主機請求隊列大小
    if (runningAsyncCalls.size() < 64 && runningCallsForHost(call) < 5) {
     
 //將Runnable添加到正在執行的異步請求隊列  
      runningAsyncCalls.add(call);
     
 //線程池來執行此Runnable
      executorService().execute(call);
    } else {
     
 //否則將Runnable添加到正在等待的異步請求隊列
      readyAsyncCalls.add(call);
    }
  }    



 


//Dispatcher類裏面創建線程池,雖然這裏運行的最大線程數爲Integer.MAX_VALUE,
//但是記住前面正在運行的異步隊列大小限制爲64.
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;
  }

 

 

//作爲Runnable的 AsyncCall,最終的execute()方法爲RealCall裏面的execute()方法。
@Override protected void execute() {
     
        //獲取響應回來的數據response
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          
          //回調onFailure
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          
          //回調onResponse
          responseCallback.onResponse(RealCall.this, response);
        }
      
        ......
        
        //線程池執行完線程任務後,調用此方法.
        client.dispatcher().finished(this);


    }

 

//作爲Runnable的 AsyncCall,最終的execute()方法爲RealCall裏面的execute()方法。
@Override protected void execute() {
     
        //獲取響應回來的數據response
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          
          //回調onFailure
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          
          //回調onResponse
          responseCallback.onResponse(RealCall.this, response);
        }
      
        ......
        
        //線程池執行完線程任務後,調用此方法.
        client.dispatcher().finished(this);

    }


//client.dispatcher().finished(this)的實現
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    
    synchronized (this) {
      
      //將任務從隊列中移除
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      
      //處理就緒狀態的異步請求隊列
      if (promoteCalls) promoteCalls();
     
    }
  }


 //處理就緒狀態的異步請求隊列  promoteCalls() 的實現
 private void promoteCalls() {
    
    //遍歷就緒狀態的異步請求隊列readyAsyncCalls
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall call = i.next();

      if (runningCallsForHost(call) < maxRequestsPerHost) {

        //如果滿足條件,則將任務從readyAsyncCalls移除,
        //並添加至runningAsyncCalls,然後線程池執行該任務
        i.remove();
        runningAsyncCalls.add(call);
        executorService().execute(call);
      }
    }
  }


 

核心Dispatcher類,維護着線程池executorService,和三個隊列,分別爲就緒狀態的異步請求隊列readyAsyncCalls,運行狀態的異步請求隊列runningAsyncCalls, 運行狀態的同步請求隊列runningSyncCalls。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章