Retrofit 2調(diào)用流程解析

Retrofit使用

若要請求api

https://api.github.com/users/{user}/repos

需要先創(chuàng)建一個接口

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

然后創(chuàng)建一個Retrofit對象

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

可以看到通過retrofit.create()方法,retrofit為我們創(chuàng)建了一個GitHubService的實現(xiàn),感覺很不可思議。
緊接著就可以通過這個GitHubService的實現(xiàn)對象去請求網(wǎng)絡了

Call<List<Repo>> repos = service.listRepos("octocat");

// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();

看到這里總是很疑惑,retrofit是如何用我們提供的接口來為我們創(chuàng)建出一個實例的呢?

Retrofit調(diào)用流程

從上面我們可以看到service實例是通過retrofit.create()方法獲得的,那我們不看一下這個create()方法

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  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);
            }
            return loadMethodHandler(method).invoke(args);
          }
        });
  }

可以看到該方法返回的并不是一個service接口的實例,而是一個動態(tài)代理對象,而他又是怎么通過動態(tài)代理去發(fā)送網(wǎng)絡請求的呢?我們就需要查看

return loadMethodHandler(method).invoke(args);

這行代碼的返回結(jié)果了,去查看loadMethodHandler()方法

private final Map<Method, MethodHandler> methodHandlerCache = new LinkedHashMap<>();

MethodHandler loadMethodHandler(Method method) {
    MethodHandler handler;
    synchronized (methodHandlerCache) {
      handler = methodHandlerCache.get(method);
      if (handler == null) {
        handler = MethodHandler.create(this, method);
        methodHandlerCache.put(method, handler);
      }
    }
    return handler;
}

可以看到該方法先去試圖從methodHandler的緩存map中去尋找相應的methodHandler,若不存在再去創(chuàng)建對應方法的MethodHandler,獲得了相應的MethodHandler實例后再去調(diào)用去invoke()方法來發(fā)送請求。
繼續(xù)查看MethodHandler的invoke()方法

Object invoke(Object... args) {
    return callAdapter.adapt(
        new OkHttpCall<>(callFactory, requestFactory, args, responseConverter));
}

其中callAdapter.adapt()方法負責把service中的返回類型轉(zhuǎn)換成其他類型,例如RxJavaCallAdapter把返回結(jié)果轉(zhuǎn)換成了Observable類型
可以看到adapt方法中傳入了一個OkHttpCall參數(shù),而最后發(fā)送出網(wǎng)絡請求的正是在該類的

@Override public void enqueue(final Callback<T> callback)
@Override public Response<T> execute() throws IOException

這兩個方法中。相關(guān)的Http請求信息則封裝在了requestFactory這個對象中。

這樣整個流程就清楚了,可以看到這與我們一般使用動態(tài)代理的方法是不同的。這里對動態(tài)代理的使用是通過調(diào)用動態(tài)代理對象的相應方法,去生成一個Http請求再來發(fā)送這個請求。而service接口中方法的信息則是通過反射來得到的。

</br>

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

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,711評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,361評論 25 708
  • 簡介 剛接觸Retrofit的時候,就寫了一篇簡單的使用介紹:Retrofit 2.0基本使用方法,算是對Retr...
    Whyn閱讀 3,111評論 4 24
  • 前言 在Android開發(fā)中,網(wǎng)絡請求十分常用 而在Android網(wǎng)絡請求庫中,Retrofit是當下最熱的一個網(wǎng)...
    Carson帶你學安卓閱讀 71,518評論 48 395
  • 當所給溫暖 抵不過疏離 那么便瀕臨疏離了 這時 總有一個用情至深的人 想要抓住些什么 因為 他害怕 曾經(jīng)的溫暖 將...
    SOURIRE17閱讀 174評論 0 0

友情鏈接更多精彩內(nèi)容