天天看點

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

**(2)defaultCallAdapterFactories:**擷取預設的CallAdapter.Factory,用于建立CallAdapter;

**(3)defaultConverterFactories:**擷取預設的資料轉換工廠ConverterFactory,用于建立轉換器Converter;

總結:Platform主要是用于适配不同的平台,用于擷取預設的Executor,請求擴充卡工廠類CallAdapterFactory,資料轉換工廠類ConverterFactory等;

4.2、baseUrl

baseUrl,是我們網絡請求的基礎URL;

我們進源碼裡面看一下,具體做了啥操作;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

這裡主要做了兩步操作:

1、首先第一步是通過解析這個baseUrl并傳回一個HttpUrl對象; 2、第二步是将第一步建立的HttpUrl對象指派給Builder;

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

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

然後下面還會解析URL,擷取到主機位址host,端口号port,具體源碼我就不貼了,感興趣的可以跟着源碼看一下;

4.3、Converter.Factory

這個我們上面在接受Retrofit的成員變量的時候有提過,是用于建立Converter的工廠,使用了抽象工廠的設計模式,而Converter是用來将請求傳回的資料,轉化為對應平台的資料,而這裡,我們使用的是Gson平台;

我們先來看一下這個Converter.Factory,看看其背後是怎麼實作的;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

從源碼可以看出,Converter.Factory是Converter的内部類,主要有兩個方法,一個是requestBodyConverter,用于将請求的RequestBody轉換為對應的轉換器Converter;

另一個方法是responseBodyConverter,用于将傳回的傳回體ResponseBody轉換為對應的轉換器Converter;

而轉換器Converter裡面隻有一個方法convert,用于将傳回的資料轉換為對應的類型;

我們在建立Retrofit的執行個體時,是通過GsonConverterFactory.create()來建立對應的轉換器工廠的,下面我們來看看這個Gson的轉換器工廠是怎麼實作的;

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

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

最終是走的這裡,進行了簡單的指派;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

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

  • requestBodyConverter:

在requestBodyConverter方法裡面,通過class的Type類型,建立了Gson的TypeAdapter,這個TypeAdapter很熟悉,就是我們使用gson解析會用到的類,最終通過TypeAdapter和gson的參數建立了GsonRequestBodyConverter對象,下面來瞄一眼這個類的代碼;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

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

這個方法的邏輯就是将傳進來的value值通過TypeAdapter将其轉化為ByteString,然後再傳進RequestBody作為參數來建構RequestBody對象;

這個方法我們先了解到這裡,後面在這個requestBodyConverter調用的地方再來講一下;

  • responseBodyConverter:
  • Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

這個方法和上面那個requestBodyConverter方法有點類似,也是通過class的Type類型,建立了Gson的TypeAdapter,最終通過TypeAdapter和gson的參數建立了GsonResponseBodyConverter,同理,我們也來看一下這個類的實作吧;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

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

這裡的邏輯有沒有很熟悉,就是我們經常用的gson解析,通過TypeAdapter讀取JsonReader的資料,傳回對應的資料類型,這裡的參數ResponseBody就是我們上面GsonRequestBodyConverter的convert方法生成的;

到這裡GsonConverterFactory就講的差不多了,後面我們在用到的地方再詳細講一下;

4.5、CallAdapter.Factory

CallAdapter.Factory,從命名可以看出,是用來建立CallAdapter的工廠類,使用了抽象工廠的設計模式,而CallAdapter是用于将Call轉化為我們所需要的請求類型,比如将Call轉化為RxJava的調用類型;

而CallAdapter裡面是通過adapt方法來進行轉換的,adapt是接口的一個方法,交給子類去實作,這個方法的邏輯,我們下面将Retrofit的解析時,再統一講解,這裡是需要了解這是一個轉換的方法即可;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

image.png

下面我們來看看建立CallAdapter的工廠裡面都有哪些方法,分别是用來幹嘛的;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

image.png

這個Factory的邏輯很少,隻有幾個方法,這裡我們主要關注get方法,通過get方法來擷取CallAdapter的對象,同理,這裡也是交給子類去實作;

而上面我們Retrifit的建立,在CallAdapter.Factory的添加時,使用了RxJava的工廠,也就是RxJava2CallAdapterFactory,用于将Call請求轉換為RxJava對應的請求;

下面我們來看看這個RxJava2CallAdapterFactory的實作邏輯吧;

RxJava2CallAdapterFactory的建立,也是通過RxJava2CallAdapterFactory.create()的方法,那麼我們來看下這個create方法做了啥?

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

隻是簡單的new了一個RxJava2CallAdapterFactory,而構造方法裡也沒有其他的邏輯了,隻是對Scheduler進行指派,而這裡建立時,傳的是null;

上面我們看完RxJava2CallAdapterFactory的建立後,下面我們來看一下RxJava2CallAdapterFactory是怎麼通過get方法建立一個CallAdapter的;

public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {

Class<?> rawType = getRawType(returnType);

if (rawType == Completable.class) {

// 建立RxJava2CallAdapter

return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,

false, true);

}

// 建立RxJava2CallAdapter

return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,

isSingle, isMaybe, false);

}

這個方法職責很明确,就是根據各種參數來建立RxJava的CallAdpter,也就是RxJava2CallAdapter;

這裡我們來重點關注一個RxJava2CallAdapte的adapt方法的邏輯;

public Object adapt(Call call) {

// 第一步:根據是否是異步的參數建立對應的Observable

Observable<Response> responseObservable = isAsync

? new CallEnqueueObservable<>(call)
new CallExecuteObservable<>(call);

Observable<?> observable;

// 第二步:根據各種判斷,再封裝一層Observable傳回

if (isResult) {

observable = new ResultObservable<>(responseObservable);

} else if (isBody) {

observable = new BodyObservable<>(responseObservable);

} else {

observable = responseObservable;

}

return observable;

}

這個方法的邏輯并複雜,主要是将Call請求轉化為RxJava的請求,最終傳回一個RxJava的被觀察者:Observable,用于進行RxJava類型的網絡請求,如上面的示例;

這個方法的邏輯主要有兩步,我們先來看一下第一步建立的被觀察者,這裡會先判斷是否是異步,如果是異步的話,那麼就建立CallEnqueueObservable,否則就建立CallExecuteObservable;

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

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

而第二步的封裝,這裡我們主要以BodyObservable來進行講解,這個類會對訂閱的觀察者進行封裝,在onNext方法中将body傳回;這一步可以了解為對傳回的結果進行處理;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

這裡是RxJava的用法,我預設你是會的,如果對RxJava還不熟悉的同學,可以後面去看看RxJava的用法;

到此,Retrofit的CallAdapter.Factory的邏輯就先告一段落了,下面我們來看看Retrofit的最終build()方法的邏輯;

4.5、Retrofit.Builder#build

廢話不多說,我們直接撸源碼;

public Retrofit build() {

// 判斷當callFactory(OkHttpClient)為空,就重新建立一個OkHttpClient進行指派;

okhttp3.Call.Factory callFactory = this.callFactory;

if (callFactory == null) {

callFactory = new OkHttpClient();

}

// 判斷Executor為空時,就用Platform的預設Executor進行指派,上面我們講過,這裡面使用的是主線的的Handler;

Executor callbackExecutor = this.callbackExecutor;

if (callbackExecutor == null) {

callbackExecutor = platform.defaultCallbackExecutor();

}

// 通過添加的CallAdapter.Factory來建立一個新的CallAdapter.Factory集合;

List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);

// 添加Platform的預設CallAdapter.Factory,如果我們沒有添加CallAdapter.Factory,那麼就會使用這個Platform的預設CallAdapter.Factory; callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

// 建立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.

// 添加預設的Converter.Factory

converterFactories.add(new BuiltInConverters());

// 添加自定的Converter.Factory

converterFactories.addAll(this.converterFactories);

// 添加Platform的預設Converter.Factory

converterFactories.addAll(platform.defaultConverterFactories());

// 最終建立Retrofit執行個體;

return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),

unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);

}

這個build()方法,主要是做各種參數的指派,最終通過參數來建立Retrofit的執行個體,那麼到這裡Retrofit的建立就差不多将完了,下面我們将會學習到Retrofit的核心;

為什麼我們可以通過接口定義一個類型,就可以執行請求了,對于這些方法的解析,以及參數的指派的操作是在哪裡呢?

這麼就涉及到Retrofit使用的一個很重要的設計模式了,也就是動态代理設計模式;

5、Retrofit的核心,動态代理

5.1、什麼是代理?

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

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

不直接操作,而是委托第三方來進行操作,進而達到目的;

而Java的代理分為靜态代理和動态代理;

5.2、什麼是靜态代理?

如果代理類在程式運作之前就已經存在了,那麼這種代理方式就被稱為靜态代理;

還是以上面的例子,我要買水果,來定義一個買水果的接口Operator;

public interface Operator {

// 買水果

void buyFruit();

}

而我們的代理類外賣App需要實作這個接口,同時,将需要委托的對象傳進來,在buyFruit的過程中,做了一些出來,比如去超市取貨,取完貨之後,再送貨;

public class AppAgent implements Operator {

private Operator operator;

public AppAgent(Operator operator) {

this.operator = operator;

}

@Override

public void buyFruit() {

// 1、在App上,提供商品給使用者下單

// 2、根據訂單去超市采購水果

operator.buyFruit();

// 3、送貨給客戶

}

}

委托的對象,超市:

public class Market implements Operator {

@Override

public void buyFruit() {

// 到超市買水果

}

}

那麼最終的實作效果就是,我們通過外賣App的一頓操作,從超市買到了水果,如下:

public class Main {

public static void main(String[] args) {

// 委托對象,超市;

Market market = new Market();

// 代理對象,外賣App;

AppAgent appAgent = new AppAgent(market);

// 通過外賣App的代理,從超市買到了水果;

appAgent.buyFruit();

}

}

以上就是我們靜态代理的過程,這個例子隻是舉了買水果這個過程,但是如果我還想要買菜,買生活用品等一系列東西呢?

我就得在接口Operator裡面再多新增好幾個方法,同樣的代理類也要跟着去重寫一堆的方法,但是這些方法做的操作其實都是一樣的,都是買這個動作,但是我們不得已,新增一種類型,我們就得在代理類裡面再重寫并調用;

那麼這個過程其實是可以抽出來的,這種方式就叫做動态代理;

5.3、動态代理

動态代理,和靜态代理不同的是,動态代理的方法是運作後才建立的,而靜态代理是運作前就存在的了;

說白了,和靜态代理不同的是,動态代理的方法都是在運作後,自動生成的,是以叫動态代理;

下面我們來看看動态代理是咋用的;

在使用動态代理的時候,被代理類需要實作InvocationHandler這個接口,,這個invoke方法是在動态生成的代理類中調用的,對應着我們上面在靜态代理operator.buyFruit()這個方法的調用,下面來看一下這個方法對應的參數;

public interface InvocationHandler {

// Object proxy:接口的具體實作類;

// Method method:解析之後自動生成的方法;

// Object[] args:方法對于的參數;

Object invoke(Object proxy, Method method, Object[] args);

}

而最終運作時生成的代理類,一般名稱會是Proxy1這種,通過Proxy.newProxyInstance()方法來生成的,這個下面會講到,先來看一下下面的僞代碼;

public final class $Proxy0 extends Proxy implements Operator {

public final boolean buyFruit() {

// h是InvocationHandlel,調用了invoke方法;

super.h.invoke(this, m1, (Object[])null);

}

}

}

在生成的代理類中,會實作我們的接口,并重寫方法,在方法裡面通過InvocationHandler回調參數到invoke方法裡,最終通過反射調用被代理對象的方法;

而我們通過實作這個InvocationHandler接口,在invoke方法裡面,通過method.invoke(object, args)可以來調用被代理的方法,然後我們可以在這個method.invoke(object, args)之前或者之後做一些處理,這樣是以的方法都可以一并進行處理,而不是每次新增一個方法,就得重寫一遍邏輯;

下面來看一下具體實作:

public class CustomProxy implements InvocationHandler {

private Object object;

public CustomProxy(Object object) {

this.object = object;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// 1、在App上,提供商品給使用者下單

// doSomeThing();

// 2、根據訂單去超市采購東西(在這個方法之前或者之後都可以統一處理操作)

Object invoke = method.invoke(object, args);

// 3、送貨給客戶

// doSomeThing();

return invoke;

}

}

下面來看一下,最終的調用;

public class Main {

public static void main(String[] args) {

// 建立被代理類

CustomProxy customProxy = new CustomProxy(new Market());

//

《Android學習筆記總結+最新移動架構視訊+大廠安卓面試真題+項目實戰源碼講義》

開源分享完整内容戳這裡

動态生成代理類

Operator proxyInstance = (Operator) Proxy.newProxyInstance(Operator.class.getClassLoader(), new Class[]{Operator.class}, customProxy);

// 調用對應的方法

proxyInstance.buyFruit();

}

}

這裡通過Proxy.newProxyInstance()方法,動态生成代理類$Proxy0這種,這裡涉及到的反射的知識,就不再贅述了;

然後動态代理類調用方法,最終會走到CustomProxy的invoke()方法,然後我們在這個方法裡面通過method.invoke(object, args)來進行最終的代理調用,而在這個最終的代理調用的前後,我們可以實作自定義的邏輯;

這個實作了InvocationHandler接口的CustomProxy,更像是一個攔截類,在代理方法的調用過程中進行攔截,然後再實作我們的自定義邏輯;

至此,動态代理你了解了嗎?沒有了解也沒關系,多看幾遍,多練幾遍就可以了;

6、Retrofit的動态代理

6.1、Retrofit為什麼要使用動态代理?

首先,讓我們來想一個問題,Retrofit為什麼要使用動态代理?

使用動态代理的好處就是在調用方法之前,我們可以統一做一些操作,而不必新增一個方法就去寫一遍邏輯;

而Retrofit巧妙的使用了動态代理在調用接口的方法之前,統一的去解析處理Header和URL等操作;

這樣就不用每次在新增一個請求的方法,就去寫一遍這個解析的邏輯;

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

6.2、Retrofit是怎麼使用動态代理的?

下面我們來看一下Retrofit的create的方法,動态代理的邏輯是在這裡實作的;

public T create(final Class service) {

// 驗證接口的參數以及配置是否正确

if (validateEagerly) {

eagerlyValidateMethods(service);

}

// 動态代理

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,如果是的話,就直接調用方法傳回

if (method.getDeclaringClass() == Object.class) {

return method.invoke(this, args);

}

// 判斷是否是Java8平台的預設方法類型,如果是的話,就調用Java8平台的invokeDefaultMethod方法

if (platform.isDefaultMethod(method)) {

return platform.invokeDefaultMethod(method, service, proxy, args);

}

// 解析方法;

return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

}

});

}

這裡我們将這個方法分為兩步;

第一步: eagerlyValidateMethods方法,這個方法的邏輯是用于加載接口的配置,用于判斷接口對應的header,body以及方法的參數等配置是否正确,如果不正确那麼就會抛出異常;

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

這裡我們重點關注第二步的loadServiceMethod方法方法;

我們來看一下其源碼的具體實作;

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中擷取,如果擷取不到了再進行解析,這樣就不必擷取一次ServiceMethod,就去解析一次,比較耗性能;

而這個ServiceMethod的類是個抽象類,隻有兩個方法,一個是靜态的parseAnnotations方法,一個是抽象的invoke方法;

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

static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {

// 通過解析接口方法的注解,擷取RequestFactory

RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

// 解析注解并擷取ServiceMethod對象

return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);

}

這個方法的邏輯也不是很複雜,主要分為兩步;

第一步: 擷取RequestFactory;

第二步: 擷取ServiceMethod;

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

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {

return new Builder(retrofit, method).build();

}

通過Builder來建立RequestFactory,來看看這個Builder做了啥操作;

Builder(Retrofit retrofit, Method method) {

this.retrofit = retrofit;

this.method = method;

// 擷取方法所有的注解,包括自己聲明的以及繼承的

this.methodAnnotations = method.getAnnotations();

// 擷取方法參數的所有類型,包含泛型;

this.parameterTypes = method.getGenericParameterTypes();

// 擷取方法參數上的所有注解

this.parameterAnnotationsArray = method.getParameterAnnotations();

}

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

RequestFactory build() {

for (Annotation annotation : methodAnnotations) {

// 周遊方法的注解,解析方法的參數配置,擷取到請求的url,header等參數

parseMethodAnnotation(annotation);

}

int parameterCount = parameterAnnotationsArray.length;

parameterHandlers = new ParameterHandler<?>[parameterCount];

for (int p = 0; p < parameterCount; p++) {

// 周遊方法的參數,以及參數的類型,解析方法的參數邏輯

parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);

}

// 根據上面解析的參數配置,建立RequestFactory

return new RequestFactory(this);

}

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

先來看一下parseMethodAnnotation這個方法, 這個方法的主要邏輯是用于解析方法注解的配置資訊;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

下面我們來看看這個類的具體實作;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

這個方法的邏輯比較多,我們大緻看一下就可以了,這裡面做的主要職責就是通過注解Annotation,擷取到url,header,isMultipart等參數,并将其指派給建造者Builder的成員變量;

對于這個方法,這裡就不多說了,感興趣的跟着源碼去看一下;

而第二個方法parseParameter,也是周遊上面擷取到的方法的參數類型parameterTypes以及方法參數的注解parameterAnnotationsArray,來解析并擷取相關配置,而這個方法最終是調的parseParameterAnnotation方法的邏輯;

主要是用于解析這裡的邏輯:

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

下面我們來看看具體實作;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

這個parseParameterAnnotation方法的邏輯和上面的parseMethodAnnotation方法有點類似,也是通過判斷對于的類型來進行解析,這裡源碼過長,就不貼出來了;

這裡我們就找其中一個Query的解析來進行分析;

省略前面的代碼

else if (annotation instanceof Query) {

// 将注解annotation強轉為Query

Query query = (Query) annotation;

// 擷取注解Query對應的值;

String name = query.value();

if (Iterable.class.isAssignableFrom(rawParameterType)) {

// 判斷這個參數的類型為Class類型;

// 建立ParameterHandler的子類Query

return new ParameterHandler.Query<>(name, converter, encoded).iterable();

}

}

省略後面的代碼

這裡最終解析擷取的是ParameterHandler.Query類,這個類裡面有個apply的方法,會在接口請求的時候會調用到,目的是通過請求的RequestBuilder将解析出來的參數,添加到RequestBuilder裡去;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

這裡我們了解一下就可以了;

這裡還有一個需要注意的點,就是這裡的解析,涉及到Converter這個convert方法的邏輯;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

這裡我以Body為例,在Body這個類的apply方法裡,會通過Converter這個convert方法,将body參數轉化為對應類型的資料;

這個apply的方法是在進行網絡請求的時候會調用,具體調用鍊如下,這裡以RxJava為例:

1、RxJavaCallAdapterFactory.ResponseCallAdapter的adapt方法;

2、RxJavaCallAdapterFactory.CallOnSubscribe的call方法;

3、RxJavaCallAdapterFactory.RequestArbiter的request方法;

4、OkHttpCall的execute方法;

5、OkHttpCall的createRawCall方法;

6、RequestFactory的create方法;

7、ParameterHandler的apply方法;

最終在這裡觸發了apply方法的調用,這裡源碼就不貼出來了,感興趣的朋友,可以跟着源碼去看一遍;

我們上面看的RequestFactory的build方法的最後一個,建立RequestFactory,這裡的邏輯就是将我們上面解析出來的參數,給這個RequestFactory進行指派;

Android 網絡架構之Retrofit源碼解析,2021華為Android面試真題解

那麼到這裡parseAnnotations的第一步就講完了,先來總結一下,這一步主要是解析方法注解和方法參數的注解,進而擷取到對應的參數配置,最終将其指派給RequestFactory對象;

下面我們來看HttpServiceMethod的parseAnnotations方法;

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(

Retrofit retrofit, Method method, RequestFactory requestFactory) {

// 建立CallAdapter

CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);

// 建立Converter

Converter<ResponseBody, ResponseT> responseConverter =

createResponseConverter(retrofit, method, responseType);

// 通過參數建立HttpServiceMethod

okhttp3.Call.Factory callFactory = retrofit.callFactory;

return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);

}

這個方法的邏輯并不複雜,主要分三步:

第一步: 建立CallAdapter;

第二步: 建立Converter;

第三步: 通過參數建立HttpServiceMethod;

這裡主要關注的是前兩步,建立了CallAdapter和Converter;

我們先來看一下第一步的邏輯;

這裡的調用鍊是這樣的,首先調用了HttpServiceMethod的createCallAdapter方法,然後再調用了Retrofit的callAdapter方法,最後調用了Retrofit的nextCallAdapter方法;

我們來看看nextCallAdapter的邏輯;

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,

Annotation[] annotations) {

// 通過callAdapterFactories的get方法來建立CallAdapter

int start = callAdapterFactories.indexOf(skipPast) + 1;

for (int i = start, count = callAdapterFactories.size(); i < count; i++) {

CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);

if (adapter != null) {

return adapter;

}

}

}

這裡的邏輯不複雜,最終通過CallAdapter.Factory來建立CallAdapter,而這個CallAdapter.Factory的邏輯我們上面已經講過了,就是用來建立CallAdapter的工廠;

下面我們來看第二步的調用;

第二步的調用鍊是這樣的,先調用HttpServiceMethod的createResponseConverter方法,然後再調用Retrofit的responseBodyConverter方法,最終調用了Retrofit的nextResponseBodyConverter方法,我們來看看nextResponseBodyConverter這個方法的邏輯;

public Converter<ResponseBody, T> nextResponseBodyConverter(

@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {