獨特的架構方式,Retrofit源碼簡析。

retrofit2.0

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)用接口中的方法時,都會運行InvocationHandlerinvoke()方法。

重點就在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 **

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容