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
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)的轉換器,也是使用的構造器模式。