Retrofit源碼解讀(五)--okhttpCall和adapt方法

Retrofit源碼解讀(五)–okhttpCall和adapt方法

標籤(空格分隔): Retrofit源碼 學習筆記


前言

  • 以下的相關知識總結是通過慕課網的相關學習和自己的相關看法,如果有需要的可以去查看一下慕課網的相關教學,感覺還可以。

內容

上一節總結了ServiceMethod的類和相關作用,接下來就總結一下下面的兩行方法.

OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);

OkHttpCall(實現了okhttp的Call)

成員變量

  //ServiceMethod對象 用來表述網絡請求參數信息
  private final ServiceMethod<T, ?> serviceMethod;
  //表述網絡接口參數
  private final @Nullable Object[] args;
 //該請求是否可以被取消  狀態標誌位
  private volatile boolean canceled;
  //okhttp3.Call   實際進行網絡請求的類
  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;
  //異常  出現異常的處理類
  @GuardedBy("this")
  private @Nullable Throwable creationFailure; // Either a RuntimeException or IOException.
  //標誌位  用於異步方法執行邏輯使用
  @GuardedBy("this")
  private boolean executed;

構造函數

//ServiceMethod   請求接口參數
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

OkHttpCall就是Retrofit這個庫對於OkHttp的一個封裝,請求網絡的時候,不管事同步還是異步,都是通過OkHttpCall進行的請求

serviceMethod.callAdapter.adapt(okHttpCall);

通過調用adapt這個方法就是用來進行適配的,通過傳入創建好的okhttpcall來獲取他的返回值
我們可以看到callAdapter是屬於serviceMethod裏面的參數,這個參數的賦值在serviceMethod的build的時候進行的賦值。adapt也就是通過適配器模式,轉換成我們需要的一些請求,比如當我們addCallAdapterFactory(RxJavaCallAdapterFactory.create())的時候,我們想要的就是通過RxJava來處理請求返回的response,那麼通過adapt這個方法就可以轉換成Observable這個類型,來讓我們操作。也就是可以對於不同平臺的其他類型。

所以當通過crete這個方法之後,我們就創建了 TestInterface service = getRetrofit().create(TestInterface.class);這個接口實例,然後通過接口實例的

service.getQiuShiJsonString()

但是有個疑問,那就是接口實例調用方法,這個時候我們可以想到的就是前面提到的動態代理,榮光Proxy.newProxyInstance進行攔截,然後調用InvocationHandler中的invoke()方法來進行實際的操作,最終我們會返回一個OkHttpcall類型的call對象來進行實際的網絡請求,所以說我們的service.getQiuShiJsonString()這個請求,就是通過動態代理返還給我們的call對象來進行網絡請你去,這個okhttpcall又是對okhttp的網絡請求的封裝,所以也就是通過okhttp來進行的同步和異步請求。

Retrofit請求

  • 同步請求OkHttpCall.execute()
  • 異步請求OkHttpCall.enqueue(callback)

經過之前的分析,我們可以知道Retrofit的Call其實是對於OkHttpCall的請求的封裝,因此Retrofit的同步和異步請求就是調用OkHttpCall的請求來進行的同步和異步

同步VS異步

  • 回調執行器
    • 整個的同步和異步請求比較類似,區別在於回調執行器,異步會把數據返回之後交給execute(回調執行器來做),由Executor來指定相應的線程去完成不同的操作

Retrofit同步請求

  • 1、ParameterHandler進行請求方法的參數解析
  • 2、根據ServiceMethod這個對象創建OkHttp的Request對象
    • 有了這個request對象我們才能調用okhttp進行網絡請求
    • 而且ServiceMethod包含了我們所有的網絡請求的基本信息(當前請求和已經換成的請求)
    • 而且這個ServiceMethod有緩存,使用的是ConcurrentHashMap,進行緩存是爲了高效運行
  • 3、通過okhttpCall發送網絡請求
  • 4、調用converter進行數據解析(默認是GsonConverter)
 qiuShiJson.execute();  //同步請求方法


 @Override public Response<T> execute() throws IOException {
    //創建okhttp3 裏面的Call對象  來請求數據
    okhttp3.Call call;
    //加鎖
    synchronized (this) {
     //是否執行的標誌位  
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
      call = rawCall;
      if (call == null) {
        try {
        //創建一個新的okhttpcall
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
    }
    //當canceled爲true的時候 直接取消請求
    if (canceled) {
      call.cancel();
    }
    //接下來分析這個parseResponse()方法  因爲call.execute()這個call其實就是okhttp的call,然後這個請求就已經交給了okhttp進行請求,這裏暫不做相關分析
    return parseResponse(call.execute());
  }

  //創建okhttp3.Call
   private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    //創建okhttp call
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
   //直接返回
    return call;
  }
  //上述方法就是把我們網絡請求中的參數,調用ParameterHandler對象來進行參數的解析,然後在通過serviceMethod.toRequest()方法來生成Request這個對象,最後把這個Request對象通過serviceMethod的CallFactory工廠的newCall()方法創建我們的實際請求的OkHttp.Call對象

parseResponse(call.execute())方法
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    //獲取到ResponseBody
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();
    //返回碼  暫不解析。。。


    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    //主要是這個toResponse()方法     最終也就是調用我們傳入的GsonConverter轉換器  轉換成我們需要的數據類型
    /** Builds a method return value from an HTTP response body. 
  //R toResponse(ResponseBody body) throws IOException //{
  //  return responseConverter.convert(body);
  //}
      T body = serviceMethod.toResponse(catchingBody);
      //返回成功的response  完成了整個的response解析
      return Response.success(body, rawResponse);
    }
  }

上述就是retrofit的同步請求的相關解析。其實簡單來說,retrofit就是通過接口的註解和參數,把我們的http請求進行了包裝,然後呢我們在retrofit使用的時候,然後在使用的時候我們只需要把重點放在接口的創建上,通過接口來配置方法和參數,其他都是通過他的內部來進行邏輯處理,他內部也是通過動態代理將客戶端寫好的接口中的方法轉換成ServiceMethod對象,然後通過這個ServiceMethod對象來獲取到我們需要的信息(數據轉換器/網絡適配器等、、),最終網絡底層的請求還是交給了okhttp來進行。

Retrofit異步請求

異步請求的相關原理基本和Retrofit的同步請求類似,關於那4步驟可以看Retrofit的同步請求剛開始那4條。主要的區別就是在於異步的異步回調

@Override public void enqueue(final Callback<T> callback) {
    //okhttpcall
    okhttp3.Call call;
    //錯誤
    Throwable failure;

    synchronized (this) {
    //和同步類似
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
        try {
        //創建rawCall
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
    }
    //錯誤相關邏輯處理
    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }
    //是否取消請求
    if (canceled) {
      call.cancel();
    }
    //這個纔是真正的異步請求
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
        //這個是正確請求返回數據只會  解析response
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        //調用成功的邏輯  回調執行器
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
        //失敗的時候  回調執行器
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
      //失敗的邏輯處理
      private void callFailure(Throwable e) {
        try {
        //這個就是callback  在我們自己的實現的onFailure裏面進行異常的處理
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
        //成功的返回 這個會在我們異步請求中  複寫這個onResponse方法來進行  數據邏輯處理,第一個參數是OkHttpCall   第二個參數就是response這個  也就是如果我們接受的是HttpResult<List<TestBean>>>這個類型  那麼我們返回的也是這個類型  Response<HttpResult<List<TestBean>>> response  這個response就是我們的最終解析後的數據類型
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章