Retrofit源碼學習筆記

最近看了Retrofit(2.5.0)的部分源碼,藉此博客記錄下本身對Retrofit的理解,功力善淺,若有錯誤歡迎各位大佬指正。java

一、簡單使用Retrofit進行異步請求

image.png
image.png

Retrofit的請求分爲四步設計模式

  • 一、建立Retrofit對象,在這裏添加網絡請求基地址,添加實際網絡請求對象Okhttp,添加數據轉換器工廠,支持Gson,JackSon,Guava,Java8等等,這裏咱們使用的是Gson的轉換器工廠。而後再添加CallAdapter工廠,支持Guava,Java8.Rxjava等,這裏咱們用的是RxJava2的CallAdapter工廠。
  • 二、咱們是先建立一個管理網絡請求的接口(RetrofitInterface),而後再這個接口裏去定義網絡請求。
  • 三、咱們根據RetrofitInterface定義的網絡請求接口拿到Retrofit的Call對象。
  • 四、經過Call對象的enqueue方法執行網絡請求。

二、Retorfit類分析

採用了構建者模式來構建,避免在構造方法傳入過多參數致使使用者混淆。緩存

先分析Retrofit的內部類Builder

Builder成員變量
public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;
    ......省略
    }
複製代碼

這裏只貼出了Builder類的成員變量,能夠看出這個類的成員變量很少,也就是說Retrofit的配置並不像okhttp那麼多安全

  • 一、platform表示的是平臺,由於Retrofit不止支持Android平臺他還支持Java8
  • 二、callFactory是Okhttp3.Call的Factory接口實例,這裏咱們建立時傳入的是OkhttpClient對象,默認也是OkhttpClient對象。
  • 三、baseUrl也就是咱們的網絡請求基地址
  • 四、converterFactories 是一個存放數據轉換器工廠的數據集合
  • 五、callAdapterFactories是一個存放callAdapter工廠的數據集合
  • 六、callbackExecutor默認是MainThreadExecutor這個類實例。裏面有一個主線程的handler,因此很明顯這個是作線程切換的。
  • 七、validateEagerly是一個標記位,在後面會被用到。
Builder構造方法
Builder(Platform platform) {
      this.platform = platform;
    }

    public Builder() {
      this(Platform.get());
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;

      // Do not add the default BuiltIntConverters and platform-aware converters added by build().
      for (int i = 1,
          size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
          i < size; i++) {
        converterFactories.add(retrofit.converterFactories.get(i));
      }

      // Do not add the default, platform-aware call adapters added by build().
      for (int i = 0,
          size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();
          i < size; i++) {
        callAdapterFactories.add(retrofit.callAdapterFactories.get(i));
      }

      callbackExecutor = retrofit.callbackExecutor;
      validateEagerly = retrofit.validateEagerly;
    }
複製代碼
  • 一、默認的構造方法只是調用了平臺參數的構造方法,並給platform賦值。因此在Android設備上platform是Platform的內部類Android類實例。
    image.png
  • 二、 咱們也能夠經過傳入Retrofit對象來初始化Builder,一樣platform仍是根據平臺來賦值。callFactory,baseUrl ,callbackExecutor ,validateEagerly 取的都是傳入Retrofit實例的值。converterFactories和callAdapterFactories只添加經過Builder的addConverterFactory方法和addCallAdapterFactory方法添加的Converter.Factory和CallAdapter.Factory。由於Builder的build方法會添加默認的轉換器和適配器到converterFactories和callAdapterFactories裏。簡而言之就是隻添加使用者以前構建Retrofit時傳入的Converter.Factory和CallAdapter.Factory。
Builder的build方法
public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
複製代碼
  • 一、檢測BaseUrl是否爲null,檢測callFactory 是否爲null,默認爲構建的一個OkhttpClient實例。檢測callbackExecutor 是否爲null,默認爲咱們前面提到的MainThreadExecutor實例。而後爲callAdapterFactories添加傳入的CallAdapter.Factory實例和平臺默認的CallAdapter.Factory實例。爲converterFactories 添加BuiltInConverters實例,傳入的Converter.Factory實例和平臺默認的Converter.Factory實例。
    image.png
    由上面代碼咱們能夠看出Android平臺默認的CallAdapter.Factory在7.0以上爲CompletableFutureCallAdapterFactory和ExecutorCallAdapterFactory,在7.0如下爲ExecutorCallAdapterFactory。
    image.png
    由上面代碼咱們能夠看出Android平臺默認的Converter.Factory在7.0以上爲OptionalConverterFactory,在7.0如下爲空集合。
  • 二、最後將經過這些參數構建Retrofit對象,這時會用調用Collections的unmodifiableList方法將converterFactories和callAdapterFactories都轉換爲一個只讀的快速訪問的list,UnmodifiableRandomAccessList實例。因此經過Builder構建的Retrofit對象裏面的converterFactories和callAdapterFactories實例都是隻讀的,要是進行寫操做會拋出UnsupportedOperationException異常。
    image.png

接着分析Retrofit

Retrofit的成員變量

Retrofit的成員變量和Retrofit的內部類Builder裏面的成員變量是基本一致的,這裏就不作闡述了。bash

Retrofit的create方法

咱們前面總結的Retrofit簡單異步請求的第三步就是經過調用Retrofit的creat方法來建立RetrofitInterface接口實例。咱們如今來看下內部是如何工做的。 網絡

image.png

  • 一、首先檢測傳入的Class是否是接口。
  • 二、而後接下來咱們能夠看到validateEagerly這個參數的使用了,默認是false。若是咱們設置爲true的話,會調用eagerlyValidateMethods方法。
    image.png
    這裏會遍歷傳入的RetrofitInterface接口裏面的全部方法,若是不是默認方法則繼續走156行,調用Retrofit的loadServiceMethod方法。
    image.png
    這裏能夠看到原來Retrofit裏面還有一個serviceMethodCache的成員變量,這個成員變量是一個ConcurrentHashMap,這是一個線程安全的map集合,看名字以及上面代碼咱們明白了咱們這個集合就是用來緩存Method對應的Retrofit裏面的ServiceMethod對象。最後跟蹤源碼發現經過Method構建了一個HttpServiceMethod實例。能夠看出HttpServiceMethod的成員變量都是很重要的,這裏就先不闡述了。從這裏咱們也能夠看出validateEagerly表明的含義是是否提早緩存RetrofitInterface中定義的方法到Retrofit中來。
    image.png
  • 三、咱們跳回到以前的Retrofit的create方法,Retrofit的133行建立了一個動態代理類。當RetrofitInterface接口中的方法經過代理執行的時候,便會執行這裏面InvocationHandler匿名內部類的invoke方法。接着往下判斷若是方法是來自Object的方法,則正常調用。若是是Andriod平臺默認方法,則會拋出UnsupportedOperationException異常(下圖是Platform的invokeDefaultMethod方法,內部類Android沒有重寫該方法。)
    image.png
  • 四、接下來是這個方法的核心147行,首先調用了loadServiceMethod方法,並經過ConcurrentHashMap獲取有沒有此method對應的HttpServiceMethod實例。有則直接返回,沒有則建立對應的HttpServiceMethod,緩存後便返回對應的HttpServiceMethod實例。接着再調用invoke,這裏咱們能夠看到主要是構建了一個OkhttpCall對象,而後用咱們的calladapter也就是RxJava2CallAdapter的adapt方法去處理。因此這裏咱們就能夠看出Retrofit主要是對網絡請求方法作了下封裝,實際請求和處理仍是交給了咱們的OkhttpCall和傳入的適配器和轉換器。
    image.png

三、HttpServiceMethod類

從上面咱們知道了Retrofit的Creat方法建立了一個動態代理,當咱們調用請求接口方法時,代理的invoke方法便會執行,這時候主要是經過HttpServiceMethod來解析請求接口(RetrofitInterface)中定義的網絡請求方法。因此,我這裏想多多認識HttpServiceMethod。架構

基類ServiceMethod

前面咱們提到的Retrofit的loadServiceMethod方法中,用serviceMethodCache來緩存Method實例和對應的HttpServiceMethod實例,而這個HttpServiceMethod實例是經過ServiceMethod的parseAnnotations方法得到的。 dom

image.png
parseAnnotations方法首先構建一個RequestFactory實例
image.png
這裏一樣是採用了構建者模式
image.png
獲取了method的註解,形參類型,形參註解。顯而易見,RequestFactory類就是將咱們在RetroInteface接口中定義的請求方法註解,返回值,參數類型等等進行解析並存儲。咱們接着看ServiceMethod的parseAnnotations方法,接下來是判斷method的返回值是否合法,不能包括可變類型或者通配符,而且不能爲空,不然拋出異常,也就是說咱們的網絡請求方法的返回值不能包括可變類型或者通配符,而且不能爲空。接着繼續調用子類HttpServiceMethod的parseAnnotations方法

HttpServiceMethod的parseAnnotations方法

image.png
這裏34行就是獲取咱們添加到Retorfit成員變量callAdapterFactories中的RxJava2CallAdapterFactory實例而後來建立一個RxJava2CallAdapter實例返回。接下來就是處理method的返回值類型,再經過咱們添加到Retorfit成員變量converterFactories中的GsonConverterFactory實例來建立一個GsonResponseBodyConverter實例返回。最後再經過RequestFactory實例,okhttp3.Call.Factory實例,RxJava2CallAdapter實例和GsonResponseBodyConverter實例來構建一個HttpServiceMethod實例。 由上面的這些內容咱們能夠明白HttpServiceMethod這個類的主要功能是經過RxJava2CallAdapter將獲得的RequestFactory,okhttp3.Call.Factory,GsonResponseBodyConverter實例建立一個OkHttpCall實例。

四、總結

  • 一、Retrofit內部實際用的網絡請求仍是OkHttp,咱們在接口中定義的請求方法經過反射得到註解,參數,返回值這些來建立RequestFactory實例,最後再經過RequestFactory實例來建立OkHttp的RealCall對象。
  • 二、Retrofit支持多平臺,數據轉換器和執行調度器,最大程度的知足不一樣架構。
  • 三、validateEagerly的值表明是否一開始就直接緩存網絡請求接口裏面全部的對應的HttpServiceMethod實例。
  • 四、Retrofit主要是採用動態代理的方式在咱們執行網絡請求方法的時候對其進行解析。
  • 五、Retrofit採用的大量的設計模式(構建者模式,代理模式,簡單工程模式、策略模式,適配器模式等等)可供咱們參考學習。
相關文章
相關標籤/搜索