Retrofit原始碼解讀(二)--Retrofit中網路通訊相關

若蘭__明月發表於2018-01-08

Retrofit原始碼解讀(二)--Retrofit中網路通訊相關

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


前言

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

網路通訊八步走

1、建立Retrofit例項 2、定義一個網路請求介面並對介面中的方法新增註解 3、通過 動態代理 生成網路請求物件 4、通過網路請求介面卡,將網路請求物件進行平臺適配 5、通過網路請求執行器,傳送網路請求 6、通過資料轉換器,解析伺服器返回的資料 7、通過回撥執行器,切換執行緒 8、使用者在主執行緒編寫邏輯

建立Retrofit例項

 public static Retrofit getRetrofit() {

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(10, TimeUnit.SECONDS);


        return new Retrofit.Builder()
                .client(builder.build())
                .baseUrl("http://m2.qiushibaike.com/")  //設定請求網路地址的url(基地址  這個地址一定要"/"結尾  要不會出現問題)
                .addConverterFactory(GsonConverterFactory.create()) //設定資料解析器  預設使用的Gson
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //設定支援RxJava轉換器
                .build();

    }
複製程式碼

Retrofit的成員變數

 //map物件,key值是Method 請求方法,value值是ServiceMethod  主要代表我們的網路請求方法進行註解之後的解析使用  
 //serviceMethodCache 用於快取網路請求配置,方法,資料轉換器 介面卡
  private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
//請求網路的okhttp工廠  預設的就是這個
  final okhttp3.Call.Factory callFactory;
  //請求基地址
  final HttpUrl baseUrl;
  //資料轉換器工廠集合  用於資料請求得到的response進行轉換
  final List<Converter.Factory> converterFactories;
  //網路請求介面卡工廠集合  比如RxJava的call
  final List<CallAdapter.Factory> adapterFactories;
  //回撥執行器 預設的是MainThreadExecutor
  final @Nullable Executor callbackExecutor;
  //標誌位   是否需要立即解析介面中的方法  後面解析的時候會看到
  final boolean validateEagerly;
複製程式碼

Builder內部類

內部類中的成員變數

    //平臺 ios  android  java8
    private final Platform platform;
    //請求網路的okhttp工廠  預設的就是這個
    private @Nullable okhttp3.Call.Factory callFactory;
      //請求基地址  需要轉換的 
    private HttpUrl baseUrl;
     //資料轉換器工廠集合  用於資料請求得到的response進行轉換
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
     //網路請求介面卡工廠集合  比如RxJava的call
    private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
     //回撥執行器 預設的是MainThreadExecutor
    private @Nullable Executor callbackExecutor;
      //標誌位   是否需要立即解析介面中的方法  後面解析的時候會看到
    private boolean validateEagerly;
複製程式碼

可以看到這個內部類的成員變數和retrofit的成員變數是一樣的,因為這個是建造者模式,對於一些的新增的變數和外部類是一樣的。構建者模式就是通過這些配置,將一些成員變數進行初始化

Builder無引數構造方法
 public Builder() {
      this(Platform.get());
    }
    
    可以看出Platform  這個類是個單例 通過findPlatform()方法獲取到這個單例
    
    其中的get()方法就是findPlatform()的方法
    在這個方法裡面,通過反射來獲取類名,在安卓中就是返回new Android()
    
    //也就是下方的這個Android類
    static class Android extends Platform {
    //會有一個預設的回撥執行器MainThreadExecutor  Looper.getMainLooper()  也就是主執行緒  
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

//建立預設的網路請求介面卡工廠  建立預設的網路請求介面卡回撥
//這個預設請求工廠產生的calladapter讓我們的call請求在非同步呼叫的時候會指定我們的Executor執行器 讓他執行回撥
    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
  

    
複製程式碼
Builder有引數構造方法
 Builder(Platform platform) {
 //做好Platform的初始化
      this.platform = platform;
      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      
      //在資料轉換工廠集合中新增一個內建的BuiltInConverters物件  也就是說如果當我們沒有新增或者沒有指定資料轉換工廠(一般會指定為GsonConverterFactory為我們的資料轉換工廠)
      converterFactories.add(new BuiltInConverters());
    }

複製程式碼

由此我們可以看出來,Builder這個內部類主要是構建了我們的使用平臺,配置了資料轉換器工廠(預設),網路介面卡的工廠,以及我們的Ececutor(預設值的初始化),這個地方還沒有真正的配置到retrofit的成員變數中。

baseUrl(string) 方法

 public Builder baseUrl(String baseUrl) {
    //工具類檢測我們傳入的url是否為空
      checkNotNull(baseUrl, "baseUrl == null");
      //通過parse方法將String型別的Url轉換為HttpUrl型別的成員變數
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      //最後通過baseUrl()這個方法來返回Builder這個型別
      return baseUrl(httpUrl);
    }
    
    //
      public Builder baseUrl(HttpUrl baseUrl) {
      //判空處理
      checkNotNull(baseUrl, "baseUrl == null");
      //拆分成多個片段
      List<String> pathSegments = baseUrl.pathSegments();
      //判斷集合中的最後一個是否以“/”結尾
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
      //在這裡可以看出來傳入的url必須以 “/”  結尾
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

複製程式碼

addConverterFactory()方法

  /** Add converter factory for serialization and deserialization of objects. */
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
    
    我們來看下我們傳入的Factory這個物件GsonConverterFactory
    因為我們是通過GsonConverterFactory.create()方法傳入的
    
    public static GsonConverterFactory create() {
    //建立Gson物件
    return create(new Gson());
  }
  
    public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson);
  }

 private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    //將傳入的gson物件賦值給我們GsonConverterFactory裡面建立的gson成員變數
    this.gson = gson;
  }
    
複製程式碼

addCallAdapterFactory()方法

   /**
     * Add a call adapter factory for supporting service method return types other than {@link
     * Call}.
     */
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
    
    我們來看下RxJavaCallAdapterFactory.create()
    
      public static RxJavaCallAdapterFactory createWithScheduler(Scheduler scheduler) {
    if (scheduler == null) throw new NullPointerException("scheduler == null");
    return new RxJavaCallAdapterFactory(scheduler, false);
  }
  
    private RxJavaCallAdapterFactory(Scheduler scheduler, boolean isAsync) {
    //主要的是這個Scheduler   用於RxJava中的排程器
    this.scheduler = scheduler;
    this.isAsync = isAsync;
  }


複製程式碼

由此我們可以看出來addConverterFactory()和addCallAdapterFactory()方法很類似,就是建立預設的(我們想要使用的資料轉換器和網路介面卡),並對 converterFactories 、adapterFactories這兩個進行新增資料

build()方法

public Retrofit build() {
//首先判斷baseUrl  這個不能為空  
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
    //這個網路請求執行器 用於產生call  代表實際的http請求
      okhttp3.Call.Factory callFactory = this.callFactory;
      //如果為空  就會建立一個OkHttpClient  這裡也就是說retrofit預設就是Okhttp作為底層網路請求
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
    //初始化回撥方法的執行器  用在retrofit非同步請求的時候(同步請求是不需要的)  子執行緒耗時操作-->UI執行緒更新UI
      Executor callbackExecutor = this.callbackExecutor;
      //如果為空的是 就會建立一個預設的回撥執行器  這個預設的是在platform裡面的預設建立方法  也就是主執行緒的那個
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      //網路請求介面卡集合   將成員變數當中的網路請求介面卡工廠作為引數傳到arraylist的建構函式當中  主要用於配置網路請求介面卡的工廠
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      //建立好網路請求介面卡工廠之後 新增我們這個安卓平臺的預設的網路請求介面卡
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      //
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
        //這個時候傳入到Retrofit的構造方法中  建立Retrofit物件
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
複製程式碼

這個時候我們簡單的過了建立Retrofit例項的過程,可以通過建造者模式來對相應的數值進行初始化,配置相關的資料轉換器和介面卡,最後通過build方法完成建立Retrofit的例項。

相關文章