Android 開源框架 05 --- Retrofit源碼解析

前言

在使用了Retrofit之后,你是否會有這樣的疑問:

1、為什么有OkHttp這么強大的網(wǎng)絡(luò)框架了,Retrofit還能脫穎而出?

2、Retrofit是怎么適配第三方框架的?

3、Retrofit用了哪些設(shè)計模式?

4、Retrofit為什么好用?

1、Retrofit存在的意義

Retrofit不是一個純網(wǎng)絡(luò)框架,為什么這么說呢? Retrofit是基于OkHttp框架來實現(xiàn)請求的,而Retrofit是基于OkHttp框架實現(xiàn)的一套封裝,利用動態(tài)代理實現(xiàn)了簡單的網(wǎng)絡(luò)請求實現(xiàn),并支持Gson,RxJava等第三方框架的適配,簡而言之,就是讓你的網(wǎng)絡(luò)請求更便捷,更強大了;

那么Retrofit底層到底是怎么封裝的呢? 是怎么變得更便捷,更強大了呢?

接下來讓我們來深入源碼,一探究竟!

2、Retrofit的使用

光說源碼,不講使用,總感覺有點被架空,容易找不到點;

那么接下來我們先來看一下Retrofit的簡單使用吧;

Retrofit接口:

public interface GetRequestInterface {

   @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
   Call<ResultData> getCall();

   @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
   Observable<ResultData> getObservableCall();

   @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
   Call<StudentBean> getItem(@Query("student") String student,  @Query("type") String type);
}

基礎(chǔ)請求URL:

public class BaseRequest {

   public static final String BaseURL = "https://fanyi.youdao.com/";

}

Retrofit的使用:

// Retrofit 實例的創(chuàng)建
       Retrofit retrofit = new Retrofit.Builder()
               .baseUrl(BaseRequest.BaseURL)
               .addConverterFactory(GsonConverterFactory.create())
               .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
               .build();

       // 創(chuàng)建請求接口類
       GetRequestInterface request = retrofit.create(GetRequestInterface.class);
       // ---普通網(wǎng)絡(luò)請求---    
       // 獲取請求對象Call
       Call<ResponseBody> call = request.getCall();
       // 執(zhí)行網(wǎng)絡(luò)請求
       call.enqueue(new Callback<ResponseBody>() {
           @Override
           public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
               ResponseBody body = response.body();
               Log.i("TAG", "MainActivity onResponse response:" + response.toString());
               Log.i("TAG", "MainActivity onResponse body:" + (body == null ? "null" : body.toString()));
           }

           @Override
           public void onFailure(Call<ResponseBody> call, Throwable t) {
               Log.i("TAG", "MainActivity onFailure t:" + t.toString());
           }
       });

       // ---RxJava網(wǎng)絡(luò)請求--- 
       Observable<ResultData> observableCall = request.getObservableCall();

       observableCall.subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread())
               .subscribe(new Observer<ResultData>() {
                   @Override
                   public void onSubscribe(Disposable d) {

                   }

                   @Override
                   public void onNext(ResultData resultData) {
                       Log.i("TAG", "retrofit onNext resultData:" + resultData.toString());

                   }

                   @Override
                   public void onError(Throwable e) {

                   }

                   @Override
                   public void onComplete() {
                       Log.i("TAG", "retrofit onComplete ");
                   }
               });

主要分為幾步:

(1)通過構(gòu)造者模式創(chuàng)建Retrofit實例;

(2)通過動態(tài)代理創(chuàng)建接口的實例;

(3)通過接口的實例獲取到網(wǎng)絡(luò)請求的操作類Call;

(4)通過Call來執(zhí)行網(wǎng)絡(luò)請求;

看一下大致流程圖:
image.png

3、Retrofit的創(chuàng)建

3.1、Retrofit的變量
// Retrofit 實例的創(chuàng)建
       Retrofit retrofit = new Retrofit.Builder()
               // 創(chuàng)建baseUrl
               .baseUrl(BaseRequest.BaseURL)
               // 添加GsonConverterFactory
               .addConverterFactory(GsonConverterFactory.create())
               // 添加RxJava的RxJavaCallAdapterFactory
               .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
               // 構(gòu)建Retrofit的實例
               .build();

Retrofit的構(gòu)建使用了建造者模式,這個模式的優(yōu)點就是可以構(gòu)造復(fù)雜的對象,方便擴展,并且看起來代碼比較簡潔,美觀;

在開始之前,我們先來看一下Retrofit的成員變量;
image.png

這里的變量并不是很多,我們來一個個分析;

(1)Map<Method, ServiceMethod<?>> serviceMethodCache:這是一個方法的緩存類,key為網(wǎng)絡(luò)請求的Method,比如GET,POST等,而ServiceMethod則對應(yīng)著動態(tài)代理解析后的方法類;

(2)okhttp3.Call.Factory callFactory:這個是創(chuàng)建OkHttp的工廠類;

(3)HttpUrl baseUrl:這個是基礎(chǔ)URL,網(wǎng)絡(luò)請求會帶上這個基礎(chǔ)URL;

(4)List<Converter.Factory> converterFactories:Converter.Factory的集合,Converter.Factory是將返回的數(shù)據(jù)通過這個工廠轉(zhuǎn)化為對應(yīng)的數(shù)據(jù),比如Gson的GsonConverterFactory工廠類,也就是數(shù)據(jù)轉(zhuǎn)化器工廠;

(5)List<CallAdapter.Factory> callAdapterFactories:CallAdapter.Factory的集合,CallAdapter.Factory是網(wǎng)絡(luò)請求的適配器工廠,比如把Call轉(zhuǎn)化為RxJava請求的RxJavaCallAdapterFactory工廠,也就是Call轉(zhuǎn)化工廠;

(6)Executor callbackExecutor:用于回調(diào)網(wǎng)絡(luò)請求;

(7)boolean validateEagerly:用于判斷是否需要立即解析方法,這個我們在將動態(tài)代理的時候會講到;

我們看完了Retrofit的成員變量,但是Retrofit的創(chuàng)建是通過Builder來創(chuàng)建的,下面我們來看看Retrofit的Builder的變量有哪些,分別有哪些作用;

4、Retrofit.Builder的創(chuàng)建

4.1、Retrofit.Builder的變量
image.png

從圖片可以看出,和Retrofit的變量差不多,唯一有區(qū)分的就是多了Platform和validateEagerly變量,讓我們通過源碼來看看這兩個是做什么的;

先來看一下這個Platform的賦值;
image.png

這個Platform是通過Platform.get()方法獲取的,來看看這個方法是啥邏輯;
image.png

從圖片可以看出,最終是調(diào)用的findPlatform()方法;

這個方法會返回Android,Java,Platform等類,主要是用來判斷對于的平臺,然后獲取到對于的Platform;

private static Platform findPlatform() {
   try {
     Class.forName("android.os.Build");
     // 判斷從系統(tǒng)中獲取到的SDK不為0的時候,則為Android平臺;
     if (Build.VERSION.SDK_INT != 0) {
       return new Android();
     }
   } catch (ClassNotFoundException ignored) {
   }
   try {
     Class.forName("java.util.Optional");
     // 如果不是Android平臺的話,那么就返回Java的平臺;
     return new Java8();
   } catch (ClassNotFoundException ignored) {
   }
   // 默認(rèn)的返回值;
   return new Platform();
 }

而Build.VERSION.SDK_INT的判斷邏輯為:
image.png

翻譯過來的意思就是:
當(dāng)前在此硬件上運行的軟件的SDK版本。這個值在設(shè)備啟動時不會改變,但可能會在硬件制造商提供OTA更新時改變;

下面我們來看一下這個Android類對應(yīng)的源碼:


image.png

Android類對應(yīng)的源碼不多,就幾個方法,這里我們重點關(guān)注下面這幾個方法:
(1)defaultCallbackExecutor():默認(rèn)的線程執(zhí)行器Executor,從源碼可以看出,獲取的是主線程的Hander,execute的時候,會post到主線程執(zhí)行;

image.png

(2)defaultCallAdapterFactories:獲取默認(rèn)的CallAdapter.Factory,用于創(chuàng)建CallAdapter;

(3)defaultConverterFactories:獲取默認(rèn)的數(shù)據(jù)轉(zhuǎn)換工廠ConverterFactory,用于創(chuàng)建轉(zhuǎn)換器Converter;

總結(jié):Platform主要是用于適配不同的平臺,用于獲取默認(rèn)的Executor,請求適配器工廠類CallAdapterFactory,數(shù)據(jù)轉(zhuǎn)換工廠類ConverterFactory等;

4.2、baseUrl

baseUrl,是我們網(wǎng)絡(luò)請求的基礎(chǔ)URL;

我們進(jìn)源碼里面看一下,具體做了啥操作;
image.png

這里主要做了兩步操作:
1、首先第一步是通過解析這個baseUrl并返回一個HttpUrl對象;
2、第二步是將第一步創(chuàng)建的HttpUrl對象賦值給Builder;

這里我們主要看第一步的具體操作,這里的邏輯是在HttpUrl的 parse(@Nullable HttpUrl base, String input)里,通過解析URL,判斷該請求的scheme是為http還是https,如果不是這其中一個,那么就會拋出異常,源碼我們大致看一下;
image.png

然后下面還會解析URL,獲取到主機地址host,端口號port,具體源碼我就不貼了,感興趣的可以跟著源碼看一下;

4.3、Converter.Factory

這個我們上面在接受Retrofit的成員變量的時候有提過,是用于創(chuàng)建Converter的工廠,使用了抽象工廠的設(shè)計模式,而Converter是用來將請求返回的數(shù)據(jù),轉(zhuǎn)化為對應(yīng)平臺的數(shù)據(jù),而這里,我們使用的是Gson平臺;

我們先來看一下這個Converter.Factory,看看其背后是怎么實現(xiàn)的;
image.png

從源碼可以看出,Converter.Factory是Converter的內(nèi)部類,主要有兩個方法,一個是requestBodyConverter,用于將請求的RequestBody轉(zhuǎn)換為對應(yīng)的轉(zhuǎn)換器Converter;

另一個方法是responseBodyConverter,用于將返回的返回體ResponseBody轉(zhuǎn)換為對應(yīng)的轉(zhuǎn)換器Converter;

而轉(zhuǎn)換器Converter里面只有一個方法convert,用于將返回的數(shù)據(jù)轉(zhuǎn)換為對應(yīng)的類型;

我們在創(chuàng)建Retrofit的實例時,是通過GsonConverterFactory.create()來創(chuàng)建對應(yīng)的轉(zhuǎn)換器工廠的,下面我們來看看這個Gson的轉(zhuǎn)換器工廠是怎么實現(xiàn)的;

先來看一下這個create()的方法;


image.png

最終是走的這里,進(jìn)行了簡單的賦值;
image.png

GsonConverterFactory這個工廠最重要的還是responseBodyConverter和requestBodyConverter方法,下面我們來具體分析;

  • requestBodyConverter:
    image.png

在requestBodyConverter方法里面,通過class的Type類型,創(chuàng)建了Gson的TypeAdapter,這個TypeAdapter很熟悉,就是我們使用gson解析會用到的類,最終通過TypeAdapter和gson的參數(shù)創(chuàng)建了GsonRequestBodyConverter對象,下面來瞄一眼這個類的代碼;
image.png

這個類的源碼很簡單,我們主要convert()這個方法;

這個方法的邏輯就是將傳進(jìn)來的value值通過TypeAdapter將其轉(zhuǎn)化為ByteString,然后再傳進(jìn)RequestBody作為參數(shù)來構(gòu)建RequestBody對象;

這個方法我們先了解到這里,后面在這個requestBodyConverter調(diào)用的地方再來講一下;

  • responseBodyConverter:
    image.png

這個方法和上面那個requestBodyConverter方法有點類似,也是通過class的Type類型,創(chuàng)建了Gson的TypeAdapter,最終通過TypeAdapter和gson的參數(shù)創(chuàng)建了GsonResponseBodyConverter,同理,我們也來看一下這個類的實現(xiàn)吧;
image.png

源碼很簡單,這里我們也是關(guān)注convert()這個方法;

這里的邏輯有沒有很熟悉,就是我們經(jīng)常用的gson解析,通過TypeAdapter讀取JsonReader的數(shù)據(jù),返回對應(yīng)的數(shù)據(jù)類型,這里的參數(shù)ResponseBody就是我們上面GsonRequestBodyConverter的convert方法生成的;

到這里GsonConverterFactory就講的差不多了,后面我們在用到的地方再詳細(xì)講一下;

4.4、CallAdapter.Factory

CallAdapter.Factory,從命名可以看出,是用來創(chuàng)建CallAdapter的工廠類,使用了抽象工廠的設(shè)計模式,而CallAdapter是用于將Call轉(zhuǎn)化為我們所需要的請求類型,比如將Call轉(zhuǎn)化為RxJava的調(diào)用類型;

而CallAdapter里面是通過adapt方法來進(jìn)行轉(zhuǎn)換的,adapt是接口的一個方法,交給子類去實現(xiàn),這個方法的邏輯,我們下面將Retrofit的解析時,再統(tǒng)一講解,這里是需要了解這是一個轉(zhuǎn)換的方法即可;


image.png

下面我們來看看創(chuàng)建CallAdapter的工廠里面都有哪些方法,分別是用來干嘛的;
image.png

這個Factory的邏輯很少,只有幾個方法,這里我們主要關(guān)注get方法,通過get方法來獲取CallAdapter的對象,同理,這里也是交給子類去實現(xiàn);

而上面我們Retrifit的創(chuàng)建,在CallAdapter.Factory的添加時,使用了RxJava的工廠,也就是RxJava2CallAdapterFactory,用于將Call請求轉(zhuǎn)換為RxJava對應(yīng)的請求;

RxJava2CallAdapterFactory的創(chuàng)建,也是通過RxJava2CallAdapterFactory.create()的方法,那么我們來看下這個create方法做了啥?
image.png

只是簡單的new了一個RxJava2CallAdapterFactory,而構(gòu)造方法里也沒有其他的邏輯了,只是對Scheduler進(jìn)行賦值,而這里創(chuàng)建時,傳的是null;

上面我們看完RxJava2CallAdapterFactory的創(chuàng)建后,下面我們來看一下RxJava2CallAdapterFactory是怎么通過get方法創(chuàng)建一個CallAdapter的;

public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
   Class<?> rawType = getRawType(returnType);

   if (rawType == Completable.class) {
     // 創(chuàng)建RxJava2CallAdapter
     return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
         false, true);
   }
   ...
   // 創(chuàng)建RxJava2CallAdapter
   return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
       isSingle, isMaybe, false);
 }

這個方法職責(zé)很明確,就是根據(jù)各種參數(shù)來創(chuàng)建RxJava的CallAdpter,也就是RxJava2CallAdapter;

這里我們來重點關(guān)注一個RxJava2CallAdapte的adapt方法的邏輯;

public Object adapt(Call<R> call) {
   // 第一步:根據(jù)是否是異步的參數(shù)創(chuàng)建對應(yīng)的Observable
   Observable<Response<R>> responseObservable = isAsync
       ? new CallEnqueueObservable<>(call)
       : new CallExecuteObservable<>(call);

   Observable<?> observable;
   // 第二步:根據(jù)各種判斷,再封裝一層Observable返回
   if (isResult) {
     observable = new ResultObservable<>(responseObservable);
   } else if (isBody) {
     observable = new BodyObservable<>(responseObservable);
   } else {
     observable = responseObservable;
   }
   ... 
   return observable;
 }

這個方法的邏輯并復(fù)雜,主要是將Call請求轉(zhuǎn)化為RxJava的請求,最終返回一個RxJava的被觀察者:Observable,用于進(jìn)行RxJava類型的網(wǎng)絡(luò)請求,如上面的示例;

這個方法的邏輯主要有兩步,我們先來看一下第一步創(chuàng)建的被觀察者,這里會先判斷是否是異步,如果是異步的話,那么就創(chuàng)建CallEnqueueObservable,否則就創(chuàng)建CallExecuteObservable;

這兩個的區(qū)別就是,在調(diào)用訂閱(subscribe)的時候,會執(zhí)行CallEnqueueObservable的subscribeActual方法,最終是通過OkHttpCall的enqueue方法來執(zhí)行異步請求;

而CallExecuteObservable在調(diào)用訂閱(subscribe)的時候,也會執(zhí)行CallEnqueueObservable的subscribeActual方法,在這個方法里,就直接調(diào)用OkHttpCall的execute方法來執(zhí)行同步請求;

而第二步的封裝,這里我們主要以BodyObservable來進(jìn)行講解,這個類會對訂閱的觀察者進(jìn)行封裝,在onNext方法中將body返回;這一步可以理解為對返回的結(jié)果進(jìn)行處理;

image.png
4.5、Retrofit.Builder#build
public Retrofit build() {
     // 判斷當(dāng)callFactory(OkHttpClient)為空,就重新創(chuàng)建一個OkHttpClient進(jìn)行賦值;
     okhttp3.Call.Factory callFactory = this.callFactory;
     if (callFactory == null) {
       callFactory = new OkHttpClient();
     }

     // 判斷Executor為空時,就用Platform的默認(rèn)Executor進(jìn)行賦值,上面我們講過,這里面使用的是主線的的Handler;
     Executor callbackExecutor = this.callbackExecutor;
     if (callbackExecutor == null) {
       callbackExecutor = platform.defaultCallbackExecutor();
     }

     // 通過添加的CallAdapter.Factory來創(chuàng)建一個新的CallAdapter.Factory集合;
     List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);

// 添加Platform的默認(rèn)CallAdapter.Factory,如果我們沒有添加CallAdapter.Factory,那么就會使用這個Platform的默認(rèn)CallAdapter.Factory;                     callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

     // 創(chuàng)建Converter.Factory的集合
     List<Converter.Factory> converterFactories = new ArrayList<>(
         1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

     // Add the built-in converter factory first. This prevents overriding its behavior but also
     // ensures correct behavior when using converters that consume all types.
     // 添加默認(rèn)的Converter.Factory
     converterFactories.add(new BuiltInConverters());
     // 添加自定的Converter.Factory
     converterFactories.addAll(this.converterFactories);
     // 添加Platform的默認(rèn)Converter.Factory
     converterFactories.addAll(platform.defaultConverterFactories());
     // 最終創(chuàng)建Retrofit實例;
     return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
         unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
   }

這個build()方法,主要是做各種參數(shù)的賦值,最終通過參數(shù)來創(chuàng)建Retrofit的實例,那么到這里Retrofit的創(chuàng)建就差不多將完了,下面我們將會學(xué)習(xí)到Retrofit的核心;

為什么我們可以通過接口定義一個類型,就可以執(zhí)行請求了,對于這些方法的解析,以及參數(shù)的賦值的操作是在哪里呢?

這么就涉及到Retrofit使用的一個很重要的設(shè)計模式了,也就是動態(tài)代理設(shè)計模式;

5、Retrofit的核心,動態(tài)代理

5.1、什么是代理?

舉個例子,假如我要去超市買水果,可是我好懶,周末就想呆在家里不想出門,但是心里又很想吃水果,那怎么辦呢?

只能打開外賣App,在上面買完之后,由外賣小哥送過來,這時候,我就通過中介,外賣App來買到水果,而這個過程叫做代理;

不直接操作,而是委托第三方來進(jìn)行操作,從而達(dá)到目的;

而Java的代理分為靜態(tài)代理和動態(tài)代理;

5.2、什么是靜態(tài)代理?

如果代理類在程序運行之前就已經(jīng)存在了,那么這種代理方式就被稱為靜態(tài)代理;

5.3、動態(tài)代理

動態(tài)代理,和靜態(tài)代理不同的是,動態(tài)代理的方法是運行后才創(chuàng)建的,而靜態(tài)代理是運行前就存在的了;

說白了,和靜態(tài)代理不同的是,動態(tài)代理的方法都是在運行后,自動生成的,所以叫動態(tài)代理;

6、Retrofit的動態(tài)代理

6.1、Retrofit為什么要使用動態(tài)代理?

首先,讓我們來想一個問題,Retrofit為什么要使用動態(tài)代理?

使用動態(tài)代理的好處就是在調(diào)用方法之前,我們可以統(tǒng)一做一些操作,而不必新增一個方法就去寫一遍邏輯;

而Retrofit巧妙的使用了動態(tài)代理在調(diào)用接口的方法之前,統(tǒng)一的去解析處理Header和URL等操作;這樣就不用每次在新增一個請求的方法,就去寫一遍這個解析的邏輯;

那么接下來我們來看看Retrofit的怎么解析這些接口的;

6.2、Retrofit是怎么使用動態(tài)代理的?

下面我們來看一下Retrofit的create的方法,動態(tài)代理的邏輯是在這里實現(xiàn)的;

public <T> T create(final Class<T> service) {
   ...
   // 驗證接口的參數(shù)以及配置是否正確
   if (validateEagerly) {
     eagerlyValidateMethods(service);
   }
   // 動態(tài)代理
   return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
       new InvocationHandler() {
         private final Platform platform = Platform.get();
         private final Object[] emptyArgs = new Object[0];

         @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
             throws Throwable {
           // 判斷是否是Object,如果是的話,就直接調(diào)用方法返回
           if (method.getDeclaringClass() == Object.class) {
             return method.invoke(this, args);
           }
           // 判斷是否是Java8平臺的默認(rèn)方法類型,如果是的話,就調(diào)用Java8平臺的invokeDefaultMethod方法
           if (platform.isDefaultMethod(method)) {
             return platform.invokeDefaultMethod(method, service, proxy, args);
           }
           // 解析方法;
           return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
         }
       });
 }

這里我們將這個方法分為兩步;

  • 第一步: eagerlyValidateMethods方法,這個方法的邏輯是用于加載接口的配置,用于判斷接口對應(yīng)的header,body以及方法的參數(shù)等配置是否正確,如果不正確那么就會拋出異常;

  • 第二步: loadServiceMethod方法,這個方法的邏輯主要是用于解析我們在接口配置的注解以及參數(shù),比如header,body,url等等;

這里我們重點關(guān)注第二步的loadServiceMethod方法方法;

我們來看一下其源碼的具體實現(xiàn);

ServiceMethod<?> loadServiceMethod(Method method) {
   // 先從緩存map集合里面獲取ServiceMethod;
   ServiceMethod<?> result = serviceMethodCache.get(method);
   if (result != null) return result;

   synchronized (serviceMethodCache) {
     result = serviceMethodCache.get(method);
     if (result == null) {
       // 如果從緩存map里面獲取不到ServiceMethod,那么再通過解析注解,獲取到ServiceMethod對象;
       result = ServiceMethod.parseAnnotations(this, method);
       // 將解析后的ServiceMethod對象存入到map集合中;
       serviceMethodCache.put(method, result);
     }
   }
   return result;
 }

這里做的操作很簡單,就是獲取ServiceMethod,而在獲取ServiceMethod的過程中,會先從緩存的map中獲取,如果獲取不到了再進(jìn)行解析,這樣就不必獲取一次ServiceMethod,就去解析一次,比較耗性能;

而這個ServiceMethod的類是個抽象類,只有兩個方法,一個是靜態(tài)的parseAnnotations方法,一個是抽象的invoke方法;

我們先來看一下這個parseAnnotations方法;

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
   // 通過解析接口方法的注解,獲取RequestFactory
   RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

   ...
   // 解析注解并獲取ServiceMethod對象
   return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
 }

這個方法的邏輯也不是很復(fù)雜,主要分為兩步;

  • 第一步: 獲取RequestFactory;
  • 第二步: 獲取ServiceMethod;

我們先來看第一步的操作;

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
   return new Builder(retrofit, method).build();
 }

通過Builder來創(chuàng)建RequestFactory,來看看這個Builder做了啥操作;

Builder(Retrofit retrofit, Method method) {
     this.retrofit = retrofit;
     this.method = method;
     // 獲取方法所有的注解,包括自己聲明的以及繼承的
     this.methodAnnotations = method.getAnnotations();
     // 獲取方法參數(shù)的所有類型,包含泛型;
     this.parameterTypes = method.getGenericParameterTypes();
     // 獲取方法參數(shù)上的所有注解
     this.parameterAnnotationsArray = method.getParameterAnnotations();
   }

這個方法的邏輯很簡單,就是做一些賦值操作,這里需要注意的是這幾個反射的方法,下面的build方法會用到;

RequestFactory build() {
     for (Annotation annotation : methodAnnotations) {
       // 遍歷方法的注解,解析方法的參數(shù)配置,獲取到請求的url,header等參數(shù)
       parseMethodAnnotation(annotation);
     }

     ...
     int parameterCount = parameterAnnotationsArray.length;
     parameterHandlers = new ParameterHandler<?>[parameterCount];
     for (int p = 0; p < parameterCount; p++) {
       // 遍歷方法的參數(shù),以及參數(shù)的類型,解析方法的參數(shù)邏輯
       parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
     }

     ...
     // 根據(jù)上面解析的參數(shù)配置,創(chuàng)建RequestFactory
     return new RequestFactory(this);
   }

這個方法的邏輯就比較重要了,我們在接口的方法里面定義的相關(guān)url,header等注解,最終就是在這里解析并轉(zhuǎn)化為okhttp請求的Call,那么我們來看看這里到底是怎么解析的;

先來看一下parseMethodAnnotation這個方法, 這個方法的主要邏輯是用于解析方法注解的配置信息;
image.png

下面我們來看看這個類的具體實現(xiàn);
image.png

這個方法的邏輯比較多,我們大致看一下就可以了,這里面做的主要職責(zé)就是通過注解Annotation,獲取到url,header,isMultipart等參數(shù),并將其賦值給建造者Builder的成員變量;

而第二個方法parseParameter,也是遍歷上面獲取到的方法的參數(shù)類型parameterTypes以及方法參數(shù)的注解parameterAnnotationsArray,來解析并獲取相關(guān)配置,而這個方法最終是調(diào)的parseParameterAnnotation方法的邏輯;

主要是用于解析這里的邏輯:
image.png

下面我們來看看具體實現(xiàn);
image.png

7、總結(jié)

從上面的分析可以看出,Retrofit最重要的點,就是動態(tài)代理,在動態(tài)代理的時候做了很多邏輯處理,簡化我們后面的調(diào)用等等;

下面我們來看最終的總結(jié)流程圖:

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容