[Android] Retrofit 源碼分析之 Retrofit 對象

前言

在上一周學習了一下 Retrofit 的執(zhí)行流程。接下來的文章要更為深入地學習 Retrofit 的各個類,這次我們先學習一下 Retrofit 框架里的 Retrofit 對象,有沒有十分的拗口。。

本文主要講 Retrofit 對象的創(chuàng)建及其 .create 方法。基本包括了這個類的全部內容。

Retrofit 對象

簡介

Retrofit 通過使用方法上的『注解』來定義請求的構成,將我們聲明的 Http 接口轉化成一個 Call 對象。

這個 Call 對象呢,我們上周提到過,可以調用同步或非同步方法來發(fā)送請求,之后就交給 OkHttp 去執(zhí)行啦。

使用

Retrofit 類用到了創(chuàng)建者模式,我們需要使用 Retrofit.Builder 來創(chuàng)建它的實例,接著調用 Retrofit.create(Class<T>) 方法就能夠生成我們的接口實現類了。

這里回顧一下 Retrofit 相關的使用:

Retrofit retrofit = new Retrofit.Builder()
 .baseUrl("https://api.example.com/")
 .addConverterFactory(GsonConverterFactory.create())
 .build();

 MyApi api = retrofit.create(MyApi.class);

Retrofit.Builder

Retrofit.Builder 是 Retrofit 對象的一個嵌套類,負責用來創(chuàng)建 Retrofit 實例對象,使用『建造者模式』的好處是清晰明了可定制化。

在執(zhí)行 .build() 方法前,只有 .baseUrl() 是必須調用來設置訪問地址的,其余方法則是可選的。

首先看一下 Builder.build() 最后的返回語句:

return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
      callbackExecutor, validateEagerly);

這里的參數包括了 Call 工廠,地址,轉換器,CallAdapter 工廠, 執(zhí)行 Callback 的線程池以及 validateEagerly 標識。

下面我們挑選其中幾個參數來進行分析:

baseUrl

baseUrl 其實是 okHttp3 的 HttpUrl 類實例,一個 http 或者 https 協議的 URL。

為 Retrofit.Builder 添加 baseUrl,有兩個重載的方法 baseUrl(String baseUrl) 和 baseUrl(HttpUrl baseUrl),但實際最后調用的都是后者。

public Builder baseUrl(HttpUrl baseUrl) {
  checkNotNull(baseUrl, "baseUrl == null");
  List<String> pathSegments = baseUrl.pathSegments();
  if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
    throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
  }
  this.baseUrl = baseUrl;
  return this;
}

可以看到,檢查驗證后就設置了 Retrofit 對象的 URL。

callbackExecutor

callbackExecutor 是 Callback 調用中用于執(zhí)行 Callback 的 線程池。

如果不自行設置的話,會根據平臺設置一個默認的 Executor。

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

這里的 .defaultCallbackExecutor() 是 Platform 抽象類的一個方法。包含了 Converter,Client 等屬性。他有三個實現類:Android,Java8,IOS。分別設置了各個平臺下的一些默認參數。

在創(chuàng)建 Retrofit.Buidler 時會獲取并設置當前環(huán)境的 Platform:

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

最后我們找到 Platform 的安卓實現類看一下:

static class Android extends Platform {
  @Override public Executor defaultCallbackExecutor() {
  return new MainThreadExecutor();
}

  @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
  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);
    }
  }
}

了解過 Handler 機制的同學肯定十分眼熟,這里獲取了主線程的 Looper 并構造了一個 主線程的 Handler,于是在 Android 平臺,調用 Callback 時會將該請求 post 到主線程上去執(zhí)行。

validateEagerly 標識

validateEagerly 是一個布爾類型的參數

我們知道當我們調用接口方法時,代理類會為方法創(chuàng)建一個 ServiceMethod。

public <T> T create(final Class<T> service) {
  Utils.validateServiceInterface(service);
  if (validateEagerly) {
  eagerlyValidateMethods(service);
  }
  ...
}

如果將 validateEagerly 標識設置為 True,那么在我們調用 .eagerlyValidateMethods(service) 方法之前就提前驗證并創(chuàng)建好啦。

以上便是 Retrofit.Builder 的一些參數和方法,更具體的大家可以參照官方文檔來學習。

.create 方法

現在我們通過嵌套類 build 了一個 Retrofit 對象,就可以開始執(zhí)行下一步了。

// 將 Http 接口 轉化為 Call 對象
MyApi api = retrofit.create(MyApi.class);

我們先直接把 create 方法的代碼丟上來,代碼并不是很多:

public <T> T create(final Class<T> service) {
  Utils.validateServiceInterface(service);
  if (validateEagerly) {
  eagerlyValidateMethods(service);
  }
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
    new InvocationHandler() {
      private final Platform platform = Platform.get();

      @Override public Object invoke(Object proxy, Method method, Object... args)
          throws Throwable {
        // If the method is a method from Object then defer to normal invocation.
        if (method.getDeclaringClass() == Object.class) {
          return method.invoke(this, args);
        }
        if (platform.isDefaultMethod(method)) {
          return platform.invokeDefaultMethod(method, service, proxy, args);
        }
        ServiceMethod serviceMethod = loadServiceMethod(method);
        OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
        return serviceMethod.callAdapter.adapt(okHttpCall);
      }
    });
}

下面一步步進行分析:

Utils.validateServiceInterface(service);

validateServiceInterface(service) 會驗證我們的 Http 接口是否是 Interface,是否未包含了其他的接口。若為否則會拋出錯誤。

if (validateEagerly) {
  eagerlyValidateMethods(service);
}

validateEagerly 的標簽的作用則在之前已經說過了,算是一個提前驗證標識。

接下來便返回了一個動態(tài)代理,其實仔細看會發(fā)現這里只是返回了動態(tài)代理的實例方法而已:

return (T) Proxy.newProxyInstance(...);

代理類首先獲取了當前的平臺 Platform,然后當你調用接口方法時,會調用到代理類的 invoke 方法。

我們看看 invoke 方法里到底做了什么:

if (method.getDeclaringClass() == Object.class) {
  return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
    return platform.invokeDefaultMethod(method, service, proxy, args);
}

如果我們調用的是來自 Object 類或者平臺默認的方法,則會交給方法執(zhí)行或者平臺執(zhí)行,但從代碼上看 isDefaultMethod(method) 直接返回的是 false,可能是為了方便開發(fā)者擴展設置各個平臺的不同方法調用。

ServiceMethod serviceMethod = loadServiceMethod(method);

經過兩個判斷后,會將我們的方法轉換成一個 ServiceMethod 對象,我們可以來看看 loadServiceMethod 方法內發(fā)生了什么:

ServiceMethod loadServiceMethod(Method method) {
  ServiceMethod result;
  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
    result = new ServiceMethod.Builder(this, method).build();
    serviceMethodCache.put(method, result);
    }
  }
  return result;
}

代碼很簡單,每個 Method 對應一個 ServiceMethod,如果緩存里沒有,則新建一個。至于這個 ServiceMethod 是什么呢?我們具體可能要以后再詳細分析。

這里簡單的了解一下:之前我們說 Retrofit 對象的作用是將我們聲明的 Http 接口轉化成一個 Call 對象。實際上真正的工作是由 ServiceMethod 的來完成的,在其內部分析并轉換了我們自定義的注解,并生成了一個 Call 對象。

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

接下來創(chuàng)建了一個 OkHttpCall。并使用 serviceMethod.CallAdapter 對 OkHttpCall 進行了轉化。

我們在創(chuàng)建 serviceMethod 時,傳入了 Retrofit 對象作為參數,這個 CallAdapter 就是從我們最開始構建 Retrofit 時所添加的 CallAdapterFatory所生成的。如果你沒有設置的話,在 Android 平臺,系統會為你設置一個 ExecutorCallAdapterFactory。

ExecutorCallAdapter會先返回一個 CallAdapter 實現類,.adapt(okHttpCall) 就是這個類的方法。

終于,callAdapter.adapt 把 okHttpCall 轉化成了 ExecutorCallbackCall:

@Override public <R> Call<R> adapt(Call<R> call) {
    return new ExecutorCallbackCall<>(callbackExecutor, call);
}

于是我們就完成了 .create() 方法的調用,實際上 Retrofit 的使用我們也幾乎掌握了,因為之后的事情是交給 okHttp 去做的。

我們可以看看這個 ExecutorCallbackCall<>(callbackExecutor, call),參數里的 callbackExecutor,有沒有很眼熟,之前 Retrofit.Builder 我們提到的默認添加的 Executor,這里其實就是我們 APP 應用的主線程。

也就是我們的網絡請求完成后 Callback 回調的 onResponse 和 onFailure 方法,都會 post 到主線程上的 Handler 來執(zhí)行。

總結

似乎這次文章的內容有點長?總結一句話就是:Retrofit 如何將 Http 接口方法調用轉換成一個 Call 請求類。

這次我在學習代碼和寫文章到最后時,確實發(fā)現了之前的許多錯誤。目前難免會有許多理解不到位的地方,文章也寫的比較散亂,希望各位能多多提出意見。

參考資料

Retrofit 2.0.0 API

快速Android開發(fā)系列網絡篇之Retrofit

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容