
Retrofit簡單介紹:
retrofit是什么?
- Retrofit是針對于Android/Java的、基于okHttp的、一種輕量級且安全的、并使用注解的網(wǎng)絡(luò)請求框架。
- 它有哪些優(yōu)勢?
首先,Retrofit使用注解方式,簡化了我們的URL拼寫形式,而且注解含義一目了然,簡單易懂;
其次,Retrofit使用簡單,結(jié)構(gòu)層次分明,每一步都能清晰的表達出之所以要使用的寓意;
再者,Retrofit支持同步和異步執(zhí)行,使得請求變得簡單,只要調(diào)用enqueue/execute即可完成;
最后,Retrofit更大自由度的支持我們自定義的業(yè)務(wù)邏輯,如自定義Converters。
- retrofit的原理:
Retrofit使用接口+注解的形式來定義一個網(wǎng)絡(luò)請求,現(xiàn)在有很多開源框架使用了注解,如Dagger2、ButterKnife等,以及Retrofit。所不同的是他們利用注解干的事卻不一樣。 Dagger2、ButterKnife他們在編譯期間就處理注解生成代碼,提供依賴注入(依賴注入和控制反轉(zhuǎn)有時間再寫)。Retrofit則是在運行期間處理注解,通過動態(tài)代理的方式來提供AOP(面向切面)能力。
下面從Retrofit以下幾個方面來分析:
(1)建造者模式
(2)代理模式
(3)注解
- 至于HttpClient、HttpConnection、okhttp、retrofit之間聯(lián)系和區(qū)別不再展開,本文更傾向是分析retrofit的原理和源碼探索。
Retrofit的源碼簡單分析
(1)建造者模式-------創(chuàng)建Retrofit實例
//使用建造者模式創(chuàng)建Retrofit實例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.oschina.net/action/apiv2/")
.addConverterFactory(GsonConverterFactory.create())
.build();
//創(chuàng)建Github接口對象
NetApi netApi = retrofit.create(NetApi.class);
Call<NewListBean> newList = netApi.getNewList(0, 1, 10);
//NetApi接口的定義
public interface NetApi {
@GET("news_list")
public Call<NewListBean> getNewList(@Query("pageIndex") int pageIndex,@Query("catalog") int catalog,@Query("pageSize") int pageSize);
}
//執(zhí)行異步請求
newList.enqueue(new Callback<NewListBean>() {
@Override
public void onResponse(Call<NewListBean> call, Response<NewListBean> response) {
System.out.println(response.body().obj_list.get(0).author.name);
}
@Override
public void onFailure(Call<NewListBean> call, Throwable t) {
t.printStackTrace();
}
});
這里最重要的代碼就是下面這個段,使用的是建造者模式,應(yīng)該很多人都熟悉
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.oschina.net/action/apiv2/")
.addConverterFactory(GsonConverterFactory.create())
.build();
源碼如下
//1、new Rtrofit.Builder()走的就是這個構(gòu)造,Builder為Retrofit的靜態(tài)內(nèi)部類
public Builder() {
this(Platform.get());
}
//2、上一段代碼調(diào)用
Builder(Platform platform) {
this.platform = platform;
converterFactories.add(new BuiltInConverters());
}
//3、調(diào)用.baseUrl的時候調(diào)用,返回的是Builder,建造者模式
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;
}
//4、調(diào)用.build()的時候調(diào)用,返回的是retrofit實例
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);
}
(2)動態(tài)代理模式-------創(chuàng)建接口實例(代理對象)
傳入我們寫的接口的class對象,返回接口的代理對象
NetApi netApi = retrofit.create(NetApi.class);
源碼如下:
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);
}
});
}
大家可以看到返回的是
Proxy.newProxyInstance(...);
retrofit.create()方法返回了一個動態(tài)代理對象。Java動態(tài)代理就是每當(dāng)我們調(diào)用代理類里面的方法時,invoke()都會被執(zhí)行,我們就可以在invoke()插入想要執(zhí)行的代碼,并且我們可以從該方法的參數(shù)中獲取到所需要的一切信息,比如從method中獲取到方法名,從args中獲取到方法名中的參數(shù)信息等,這個就是Java的動態(tài)代理。大家可以看到Proxy.newProxyInstance(...)方法的最后一個參數(shù)就是InvocationHandler,InvocationHandler有一個方法是invoke,當(dāng)我們執(zhí)行Call<NewListBean> newList = netApi.getNewList(0, 1, 10);這段代碼的時候,返回的Proxy.newProxyInstance(...)返回的代理對象,并不是NetApi的實現(xiàn)類對象,當(dāng)我們調(diào)用netApi.getNewList(0,1,10)方法時,動態(tài)代理機制就會調(diào)用上面InvocationHandler的invoke()方法,從而我們通過代理機制在invoke()來插入我們想要加入的代碼,比如我拿我女朋友的錢包去買菜,錢包就是實際對象,我就是代理對象,我在買菜的時候需要先判斷錢包的錢夠不夠,并且我在買菜的時候才動態(tài)去判斷,這個判斷只有在買菜的時候才去判斷。這個判斷的過程就是類似invoke方法,只有方法運行的時候才被調(diào)用。點到為止,有時間專門寫一篇動態(tài)代理的。
ServiceMethod serviceMethod = loadServiceMethod(method)。。。待更新
(3)java注解-------解析(代理對象)
待更新。。。。。。。
參考文章:
Retrofit簡單原理分析
http://blog.csdn.net/lyric_315/article/details/52710464
Android 網(wǎng)絡(luò)框架之Retrofit2使用詳解及從源碼中解析原理
http://blog.csdn.net/guiman/article/details/51480497