
2016/07/21
上海
Read the fucking source code。
Retrofit,Type-safe HTTP client for Android and Java 。
GitHub:http://square.github.io/retrofit
開始之前,先回想下一個網(wǎng)絡請求的基本姿勢(默認框架搭建完成):
1,生成請求參數(shù),確定接口
2,利用NetWork模塊,發(fā)送到指定API
3,響應成功,反序列
4,響應失敗,做某些處理
5,線程調(diào)度,結果交給前臺
Retrofit作為NetWork框架,也不例外。
1,以接口+注解的形式,生成請求參數(shù),確定接口
2,利用CallFactory生成NetWork模塊,發(fā)送到指定API
3,響應成功,利用ConverterFactory反序列
4,響應失敗,做某些處理
5,請求結果經(jīng)過CallAdapterFactory包裝
6,CallAdapterFactory包裝包裝后,線程調(diào)度,結果交給前臺
目錄:
1,我們配置Retrofit時,到底發(fā)生了什么?
2,Retrofit.create(final Class<T> service)都做了什么?
3,ServiceMethod 是什么?
4,OkHttpCall 是什么?
5,serviceMethod.callAdapter.adapt(okHttpCall)是什么鬼?
6,CallFactory、okHttpCall、CallAdapter之間的關系?
問題一:我們配置Retrofit時,到底發(fā)生了什么?
</br>
//Retrofit構造器
new Retrofit.Builder()
//配置服務器
.baseUrl(UrlHelp.SERVER_IP)
//反序列工具生成器
.addConverterFactory(XmlToJsonConverterFactory.create())
.//結果包裝工具生成器(不大好描述..)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//NetWork工具生成器
.callFactory(HttpClient())
//線程調(diào)度
.callbackExecutor()
.build();
** 配置:**
ConverterFactory 反序列工具生成器
CallAdapterFactory 結果包裝工具生成器 默認為ExecutorCallAdapterFactory
okhttp3.Call.Factory NetWork工具生成器 默認為OkHttpClient
CallbackExecutor 線程調(diào)度
配置的是Retrofit的功能模塊,Retrofit將網(wǎng)絡請求流程中的各個關節(jié)(是的,關節(jié))部位打斷,使各個模塊之間相關性降到最低,再通過“配置”的方式開放出來,應對復雜的使用環(huán)境。
Retrofit(
okhttp3.Call.Factory callFactory,
HttpUrl baseUrl,
List<Converter.Factory> converterFactories,
List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories);
// Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories);
// Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
.build()方法new Retrofit()實例并返回,new Retrofit()時傳入配置信息。
問題二:Retrofit.create(final Class<T> service)都做了什么?
</br>
mRetrofit.create(RetorfitInterfaces.UserInfoServer.class)
.sendPost(userId)
.enqueue(call);
create(final Class<T> service),傳入自定義接口,返回接口實例。
在外部使用中,這是最直接的感受,實際上返回的是代理對象。
//僅摘取核心部分
public <T> T create(final Class<T> service) {
......
return (T) Proxy.newProxyInstance(
...
new InvocationHandler() {
.....
@Override
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
......
//加載ServiceMethod
ServiceMethod serviceMethod = loadServiceMethod(method);
//加載OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//調(diào)用callAdapter.adapt(okHttpCall)
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
這部分源碼寫的很直觀,簡單來說當調(diào)用接口中的方法時,都會運行InvocationHandler的invoke()方法。
重點就在invoke(Object proxy, Method method, Object... args)方法中的三句代碼:
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
問題三:ServiceMethod 是什么?
</br>
(以下省略適配、優(yōu)化等細節(jié)代碼)
//調(diào)用Retrofit.loadServiceMethod(method);加載ServiceMethod;
serviceMethod = loadServiceMethod(method);
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
....
//通過 ServiceMethod.Builder構造器創(chuàng)建實例
result = new ServiceMethod.Builder(this, method).build();
....
return result;
}
public Builder(Retrofit retrofit, Method method) {
//持有了retrofit實例,retrofit持有前面說到的各配置組件,
//也就是說ServiceMethod相當于持有各配置組件,
//變相的將四大組件組裝在了一起。
this.retrofit = retrofit;
..注解解析相關...
}
public ServiceMethod build() {
.....
//創(chuàng)建CallAdapter實例,createCallAdapter()是ServiceMethod.Builder的私有方法,在此簡寫
callAdapter = createCallAdapter(){
....
//調(diào)用了Retrofit實例的CallAdapter();CallAdapter()是Retrofit的公共方法,在此簡寫
return retrofit.callAdapter(returnType, annotations){
...
//Retrofit利用配置中的CallAdapterFactory獲取CallAdapter實例
return CallAdapterFactory.get();
};
};
......
//創(chuàng)建responseConverter 反序列工具實例,createResponseConverter()是ServiceMethod.Builder的私有方法,在此簡寫
responseConverter = createResponseConverter(){
....
//調(diào)用Retrofit實例的responseBodyConverter()方法
return retrofit.responseBodyConverter(responseType, annotations){
....
//利用converterFactory工廠創(chuàng)建反序列工具
return converterFactory.responseBodyConverter();
}
};
...注解相關...
//調(diào)用ServiceMethod的構造函數(shù)ServiceMethod(Builder builder);創(chuàng)建實例
return new ServiceMethod<>(this);
}
//ServiceMethod.Builder構造器(注意還不是ServiceMethod)持有了Retrofit實例,CallAdapter實例,responseConverter 反序列工具實例。
//ServiceMethod構建方法,參數(shù)是構造器
ServiceMethod(Builder<T> builder) {
this.callFactory = builder.retrofit.callFactory();//持有CallFactory實例
this.callAdapter = builder.callAdapter; //持有CallAdapter實例
this.baseUrl = builder.retrofit.baseUrl(); //持有BaseUrl
this.responseConverter = builder.responseConverter;//持有反序列工具
....注解相關
}
至此,ServiceMethod實例創(chuàng)建完畢,ServiceMethod變相的將各模塊組裝在一起。
問題四:OkHttpCall是什么?
</br>
先說兩個概念:
interface okhttp3.Call{
enqueue(Callback responseCallback);
execute();
request();
isExecuted();
isCanceled();
cancel();
}
interface retrofit2.Call{
同上;
clone();
}
1,retrofit2.Call與okhttp3.Call區(qū)別就是多了個clone方法,retrofit2.Call需要clone,才能再次使用。
2,OkHttpCall 實現(xiàn)了retrofit2.Call。
3,CallFactory創(chuàng)建的是okhttp3.Call實例,OkHttpClient實現(xiàn)了okhttp3.Call。
WTF??看代碼。
(以下省略適配、優(yōu)化等細節(jié)代碼)
//直接調(diào)用構造方法
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod; //持有了ServiceMethod實例
this.args = args;//注解相關
}
OkHttpCall持有serviceMethod實例,就這樣。但OkHttpCall 實現(xiàn)了retrofit2.Call,有必要看一下enqueue(Callback responseCallback);execute();
//外部傳入callBack,結果回調(diào)
enqueue(final retrofit2.Callback<T> outCallback){
//Retrofit NetWork模塊實際使用的還是okhttp3.Call,retrofit2.Call只是對外放出的包裝
okhttp3.Call call = createRawCall(){
//Retrofit 默認callFactory為OkHttpClient
return serviceMethod.callFactory.newCall(request);
};
//利用okhttp3.Call發(fā)送請求,并傳入新的CallBack();
call.enqueue(
new okhttp3.Callback() {
//成功
onResponse(okhttp3.Response rawResponse){
//parseResponse(rawResponse)是將請求結果反序列,內(nèi)部調(diào)用ServiceMethod中的responseConverter,也就是配置里的反序列化工具生成JavaBean。
rawResponse = parseResponse(rawResponse)
//將反序列化后的JavaBean傳給前臺
outCallback.onResponse(rawResponse);
}
//失敗
onFailure(Throwable e){
//將錯誤信息傳給前臺
outCallback.onFailure(e);
}
}
)
}
execute(){
...與enqueue大致相同, 也是利用CallFactory生成okhttp3.Call,調(diào)用okhttp3.Call.execute()
}
so:
1,OkHttpCall實現(xiàn)Retrofit.Call接口
2,CallFactory生成的Call對象為Okhttp3.Call接口
3,OkHttpCall持有CallFactory生成的Call對象
4,OkHttpCall在enqueue,execute方法中實際調(diào)用的是CallFactory生成的Call對象發(fā)送請求,OkHttpCall本身并沒有NetWork的功能
5,所以,OkHttpCall只是適配器,或者說包裝器,外部使用Retrofit.Call,Retrofit.Call內(nèi)部使用Okhttp3.Call,Retrofit.Call與Okhttp3.Call之間,由OkHttpCall調(diào)度
6,OkHttpCall實現(xiàn)Retrofit.Call接口,與外部來說,無需關心NetWork到底是如何發(fā)送的
問題五:
serviceMethod.callAdapter.adapt(okHttpCall)是?
</br>
先回頭擼一下
mRetrofit
//返回代理對象
.create(RetorfitInterfaces.UserInfoServer.class)
//serviceMethod.callAdapter.adapt(okHttpCall)返回retrofit2.Call對象
.sendPost(userId)
//調(diào)用返回的retrofit2.Call的enqueue方法
.enqueue(call);
沒毛病。
serviceMethod.callAdapter由Retrofit.CallAdapterFactory創(chuàng)建(上面源碼有提到)。 而CallAdapterFactory可由外部配置,默認ExecutorCallAdapterFactory。
(以下省略適配、優(yōu)化等細節(jié)代碼)
//默認ExecutorCallAdapterFactory.adapt,創(chuàng)建返回了ExecutorCallbackCall實例
@Override public <R> Call<R> adapt(Call<R> call) {
//call就是okHttpCall
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
//看看ExecutorCallbackCall又是什么,一個 Retrofit2.Call<T>實現(xiàn)類,
class ExecutorCallbackCall<T>implements Retrofit2.Call<T>{
//構造函數(shù),callbackExecutor配置中的線程池,delegate就是okHttpCall
ExecutorCallbackCall(Executor callbackExecutor, retrofit2.Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; }
//Retrofit2.Call<T>接口中的方法,發(fā)送異步請求,參數(shù)outCallBack是外部傳入的回調(diào)接口
enqueue(final Callback<T> outCallback){
//利用delegate,其實就是okHttpCall發(fā)送請求,又是包裝new Callback()
delegate.enqueue(new Callback<T>() {
//成功
onResponse(Call<T> call, final Response<T> response) {
//線程調(diào)度
callbackExecutor.execute(new Runnable() {
public void run() {
//傳給前臺
outCallBack.onResponse(
ExecutorCallbackCall.this, response
);
}
}
}
//失敗
onFailure(Call<T> call, final Throwable t){
//線程調(diào)度
callbackExecutor.execute(new Runnable() {
public void run() {
outCallBack.onFailure(ExecutorCallbackCall.this, t);
}
});
}
);
}
// ****Retrofit2.Call<T>接口中的方法,**發(fā)送同步請求**
Response<T> execute(){
//delegate 就是okHttpCall
return delegate.execute();
}
}
1,serviceMethod.callAdapter.adapt(okHttpCall)返回Retrofit2.Call實例,默認ExecutorCallbackCall
2,ExecutorCallbackCall實例中持有okHttpCall的實例
3,ExecutorCallbackCall實例中的enqueue,execute方法,方法中實際操作的還是OkHttpCall對應的方法。
4,ExecutorCallbackCall將請求結果通過制定線程(配置中的CallbackExecutor)發(fā)送到前臺
問題六:CallFactory、okHttpCall、CallAdapter之間的關系?
</br>
從上向下的包裝關系,,類似裝飾模式:
** 外部調(diào)用**
** CallAdapterFactory.CallAdapter.Retrofit.Call**
** 包裝**
okHttpCall.Retrofit.Call
** 包裝**
CallFactory.okhttp3.Call
外部調(diào)用
|---------------------------------------------------|
| CallAdapter.Retrofit.Call |
| |---------------------------------------| |
| | okHttpCall.Retrofit.Call | |
| | ----------------------------- | |
| | | CallFactory.okhttp3.Call | | |
| | ----------------------------- | |
| | | |
| |---------------------------------------| |
| |
|---------------------------------------------------|
CallFactory.okhttp3.Call面向發(fā)送請求,不關心結果處理
CallAdapterFactory.CallAdapter.Retrofit.Call面向返回結果,不關心發(fā)送
OkHttpCall.Retrofit.Call作為中間件,將兩者聯(lián)系起來
**外部實際調(diào)用的是CallAdapter生成的Retrofit.Call **