1. 程式人生 > >retrofit2原理學習(未完待續)

retrofit2原理學習(未完待續)

最簡單的okhttp+retrofit2使用demo

retrofit = new Retrofit.Builder()
        .baseUrl(
"https://api.douban.com/v2/")
        .build()
;
service= retrofit.create(RetrofitService.class);
Call<Book> call =  service.getSearchBook("金瓶梅",null, 0, 1);
call.enqueue(new Callback<Book>(){
   
@Override
   
public void

onResponse(Call<Book>call, Response<Book> response) {
       
text_tv.setText(response.body()+"");
   
}
   
@Override
   
public void onFailure(Call<Book>call, Throwable t) {
    }
})
;

這裡retrofit使用了build模式,點進去可以看到

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

Builder函式

Builder(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.   converterFactories.add(new BuiltInConverters()); }

這裡使用了一個Platform.get()函式,查閱資料可以得知,這個Platform.get()是獲得平臺資訊的函式(平臺可以是android或者是java8)。除此之外還有一個converterFactories.add(new BuiltInConverters());這個函式的主要作用是添加了一個Converter.Factory工廠類。在retrofit的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> 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);

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

沒理解錯的話,應該是一個把返回結果轉換的工廠。另外那個CallAdapter.Factory應該是新增Call或者Rxjava中Observer的類,預設情況的話,應該是Call。

而這個預設新增的BuiltInConverters再請求情況的狀態下,主要去除future I/O,其實啥也沒做就是吧response又吐出來了。

回到retrofit的build,這裡這個baseUrl是必須的,不然會報錯,原始碼裡是這樣的

public Builder baseUrl(String baseUrl) {
  checkNotNull(baseUrl, "baseUrl == null");
  HttpUrl httpUrl = HttpUrl.parse(baseUrl);
  if (httpUrl == null) {
    throw new IllegalArgumentException("Illegal URL: " + baseUrl);
  }
  return baseUrl(httpUrl);
}

這樣的話,一個retrofit物件就新建好了。

然後就到了新建介面的物件service了,原始碼裡是這樣的

@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);
          }
          ServiceMethod serviceMethod = loadServiceMethod(method);
          OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
          return serviceMethod.callAdapter.adapt(okHttpCall);
        }
      });
}

首先這個validateEagerly來自於Retrofit物件的自定義。好像預設做了點什麼,實際測了一下好像並沒有什麼區別。

講真這裡這個原理我不是很懂。好像利用了反射和代理模式相關的知識,需要單獨學一下,暫時先放一下。

這裡的SetviceMethod是retrofit的主要功能實現載體。

ServiceMethod:從介面方法到Http請求(OKHttp的Call)的轉換器,也是使用的構造器模式。