閱讀:Retrofit 源碼

Retofit入門使用

第一步:定義網絡請求接口類

public interface MyApi {
    @FormUrlEncoded
    @POST
    Call<ResponseBody> getData(@Field("userId") String userId);
}
複製代碼

第二步:初始化retrofit實例

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("這裏放基礎url")
                .build();
複製代碼

第三步:生成接口實現類

MyApi api = retrofit.create(MyApi.class);
複製代碼

第四步:調用接口方法,發起請求

Call<ResponseBody> call = api.getData("1234");
//post請求
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {

    }
});
//get請求
call.request();
複製代碼

至此,一個簡單的使用retrofit網絡請求完成。java

推薦閱讀 這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解)android

Retrofit 源碼理解

知其然知其因此然,一塊兒看看原理是怎麼實現的。api

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("這裏放基礎url")
                .build();
複製代碼

初始化分析-Builder()

建立了一個Builder對象,Buidler是Retrofit的靜態內部類bash

Builder(Platform platform) {
  this.platform = platform;
}

public Builder() {
  this(Platform.get());
}
複製代碼

這步很簡單,初始化Builder對象,調用的無參構造,方法內部將 Platform.get() 做爲參數又調用了本身的有參構造。markdown

咱們點開 Platform.get() 看看內部都作了什麼 `網絡

//靜態常量
private static final Platform PLATFORM = findPlatform();

//靜態方法
static Platform get() {
return PLATFORM;
}

//最終調用這個方法
private static Platform findPlatform() {
try {
  Class.forName("android.os.Build");
  if (Build.VERSION.SDK_INT != 0) {
    return new Android();
  }
} catch (ClassNotFoundException ignored) {
}
try {
  Class.forName("java.util.Optional");
  return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
複製代碼

這步就是根據不一樣的系統建立一個Platform對象,很顯然咱們是Android平臺。併發

總結:這一步就是 經過Platform獲得了一個Builder對象。ide

初始化分析-baseUrl()

/**
 * Set the API base URL.
 *
 * @see #baseUrl(HttpUrl)
 */
public Builder baseUrl(String baseUrl) {
  //判空
  checkNotNull(baseUrl, "baseUrl == null");
  //將字符串形式的地址 解析爲 HttpUrl
  HttpUrl httpUrl = HttpUrl.parse(baseUrl);
  //判空呀
  if (httpUrl == null) {
    throw new IllegalArgumentException("Illegal URL: " + baseUrl);
  }
  return baseUrl(httpUrl);
}

//最終調用
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;
}
複製代碼

這一步就是對設置的baseUrl進行校驗,最終輸出一個HttpUrl類型的正確地址。oop

初始化分析-build()

public Retrofit build() {
    //判空呀
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
    //okhttp的工廠實例 用於網絡請求
      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.add(platform.defaultCallAdapterFactory(callbackExecutor));

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

      // 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);

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
複製代碼

這個方法,主要就是校對參數,baseUrl不可爲空,callFactory就是okhttp的工廠實例,用於網絡請求的,其餘參數爲空則建立,最終攜帶這些參數建立了一個Retrofit實例。源碼分析

總結:以上就是 初始化階段 的源碼分析 ,比較簡單,經過鏈式設置一系列參數,最終返回一個retrofit實例。

關鍵入口 create() 方法

接下來的部分,整個過程比較長,並且是關鍵部分,通過幾番嘗試,發現 流程圖+文字分析 這種形式更加清晰。

總結

Retrofit在create方法中採用動態代理模式實現接口方法,這個過程構建了一個ServiceMethod對象,根據方法註解獲取請求方式,參數類型和參數註解拼接請求的連接,當一切都準備好以後會把數據添加到Retrofit的RequestBuilder中。而後當咱們主動發起網絡請求的時候會調用okhttp發起網絡請求,okhttp的配置包括請求方式,URL等在Retrofit的RequestBuilder的build()方法中實現,併發起真正的網絡請求。

心得

  • 沒必要深究源碼細節,不影響大流程的看不懂的直接跳過
  • 多看幾遍,每多看一遍會發現其實還沒弄懂
  • 參照別人的文章看完,要本身寫寫或者畫畫流程圖

感謝

這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解)

Retrofit原理解析最簡潔的思路

一文學會 Java 動態代理機制

相關文章
相關標籤/搜索