現(xiàn)如今兆旬,Android開發(fā)中,網(wǎng)絡(luò)層Retrofit+Okhttp組合好像已成標配宿饱,身為技術(shù)人員脚祟,這么火的框架當(dāng)然得一探究竟由桌,不為裝逼,純粹是為了充電而已碍舍。
基本使用介紹
介紹源碼前邑雅,我們先看下Retrofit的基本使用,大致了解下流程捧书,跟著這個流程來分析源碼才不會亂。
- 初始化Retrofit對象
Retrofit retrofit = new Retrofit.Builder()
//使用自定義的mGsonConverterFactory
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://apis.baidu.com/txapi/")
.build()爆哑;
- 定義接口
public interface APi {
@GET("hello/world")
Call<News> getNews(@Query("num") String num,@Query("page")String page);
}
- 發(fā)起網(wǎng)絡(luò)請求
mApi = retrofit.create(APi.class);
Call<News> news = mApi.getNews("1", "10");
news.enqueue(new Callback<News>() {
@Override
public void onResponse(Call<News> call, Response<News> response) {
}
@Override
public void onFailure(Call<News> call, Throwable t) {
}
});
Retrofit本質(zhì)分析
看到上面的整個流程舆吮,不去探究源碼的話肯定一臉懵逼色冀,我就定義了一個接口,指定了下返回值屯换,為毛這個接口就可以直接用了与学?接口的實現(xiàn)呢?我隨便寫一個返回值晕窑,不指定返回Call行不行蕾盯?待著這些疑問蓝丙,我們大致也可以猜出Retrofit是干什么的了。
猜測:Retrofit主要就是為我們定義的接口創(chuàng)造了一個實例挫鸽,然后這個實例調(diào)用接口中的方法將我們定義在注解中的值拼裝成發(fā)起http請求所要的信息丢郊,最后利用這些信息產(chǎn)生一個我們在接口返回值中規(guī)定的對象医咨,這個對象可以用來發(fā)起真正的請求。
簡單的講干茉,Retrofit就是把注解中的東西拼成http請求的對象很泊,然后由這個對象去發(fā)起請求沾谓。
驗證猜測
是誰實現(xiàn)了這個接口
發(fā)起網(wǎng)絡(luò)請求時戳鹅,有這樣一句:
mApi = retrofit.create(APi.class);
很明顯,接口的實現(xiàn)應(yīng)該是這個create干的事妇穴,我們跟進去看看源碼:
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, @Nullable 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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
這里我們不用去看一些細節(jié)伟骨,只去關(guān)注我們想知道的携狭,這個Create方法到底干了什么回俐,看到Proxy.newProxyInstance,哦单默!這就很明顯了忘瓦,這里接口之所以能夠直接調(diào)用是使用了動態(tài)代理技術(shù),產(chǎn)生了一個代理對象境蜕。binggo凌停,一個問題解決!Lㄊ赐俗!
什么時候開始將注解中參數(shù)拼裝成http請求的信息的?
動態(tài)代理是干什么的氏仗?(大家最好單獨去學(xué)習(xí)下Java的動態(tài)代理,有時候非常有用呐舔,資料網(wǎng)上大把大把的)
使用動態(tài)代理一般是為了攔截方法珊拼,好在個方法執(zhí)行的時候流炕,在執(zhí)行之前或之后干些自己的事情。這里回顧下Retrofit的使用剑辫,通過Create方法產(chǎn)生代理對象后直接就調(diào)用定義的方法了渠欺。那么,所有的小動作必然是在調(diào)用接口方法的時候干的胳岂。具體就是invoke中的方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
前兩個if判斷主要是為了跳過object和object中內(nèi)置的一些方法乳丰,除了這些内贮,剩下的所有方法必然是我們在接口中定義的,也就是我們要攔截的什燕。那么真正干事的就是三句:
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
其中l(wèi)oadServiceMethod()方法就是用來拼裝http請求信息的拂酣,這個問題解決婶熬!
如何產(chǎn)生發(fā)起http請求對象的埃撵?
經(jīng)過上面的分析, OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);這就很明顯就是用來生產(chǎn)這個對象的饺谬。
如何將對象轉(zhuǎn)換成我們在接口中指定的返回值的?
這里要說明下族展,之前我們定義接口的時候是這樣的:
@GET("hello/world")
Call<News> getNews(@Query("num") String num,@Query("page")String page);
這里的Call和Okhttp的Call其實很像仪缸,其實連方法都幾乎一樣列肢,但是Retrofit和Rxjava一起用的時候又可以這樣定義
@GET("book/search")
Observable<Book> getSearchBook(@Query("q") String name,
@Query("tag") String tag, @Query("start") int start,
@Query("count") int count);
這里指定的返回值不再是Call,而是變成了RxJava的Observable拴还,所以這里肯定有一步轉(zhuǎn)換欧聘,能將之前拼裝的信息轉(zhuǎn)換成我們指定的對象,具體核心就是最后一行的serviceMethod.adapt()干的拇厢。
總結(jié)
經(jīng)過以上分析晒喷,我們對Retrofit大致是干什么的很清楚了,主要就是拼裝http信息衣盾,并轉(zhuǎn)換成我們要的能夠發(fā)起http請求的對象势决。本文只是一個初探蓝撇,后面我們將對每一步進行深入分析。