前言
在使用了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ò)請求;
看一下大致流程圖: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的成員變量;這里的變量并不是很多,我們來一個個分析;
(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的賦值;從圖片可以看出,最終是調(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的判斷邏輯為:翻譯過來的意思就是:
當(dāng)前在此硬件上運行的軟件的SDK版本。這個值在設(shè)備啟動時不會改變,但可能會在硬件制造商提供OTA更新時改變;
下面我們來看一下這個Android類對應(yīng)的源碼:
Android類對應(yīng)的源碼不多,就幾個方法,這里我們重點關(guān)注下面這幾個方法:
(1)defaultCallbackExecutor():默認(rèn)的線程執(zhí)行器Executor,從源碼可以看出,獲取的是主線程的Hander,execute的時候,會post到主線程執(zhí)行;
(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;
這里主要做了兩步操作:
1、首先第一步是通過解析這個baseUrl并返回一個HttpUrl對象;
2、第二步是將第一步創(chuàng)建的HttpUrl對象賦值給Builder;
然后下面還會解析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)的;從源碼可以看出,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()的方法;
GsonConverterFactory這個工廠最重要的還是responseBodyConverter和requestBodyConverter方法,下面我們來具體分析;
-
requestBodyConverter:image.png
這個類的源碼很簡單,我們主要convert()這個方法;
這個方法的邏輯就是將傳進(jìn)來的value值通過TypeAdapter將其轉(zhuǎn)化為ByteString,然后再傳進(jìn)RequestBody作為參數(shù)來構(gòu)建RequestBody對象;
這個方法我們先了解到這里,后面在這個requestBodyConverter調(diào)用的地方再來講一下;
-
responseBodyConverter: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)換的方法即可;
這個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方法做了啥?只是簡單的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)行處理;
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這個方法, 這個方法的主要邏輯是用于解析方法注解的配置信息;這個方法的邏輯比較多,我們大致看一下就可以了,這里面做的主要職責(zé)就是通過注解Annotation,獲取到url,header,isMultipart等參數(shù),并將其賦值給建造者Builder的成員變量;
而第二個方法parseParameter,也是遍歷上面獲取到的方法的參數(shù)類型parameterTypes以及方法參數(shù)的注解parameterAnnotationsArray,來解析并獲取相關(guān)配置,而這個方法最終是調(diào)的parseParameterAnnotation方法的邏輯;
主要是用于解析這里的邏輯:7、總結(jié)
從上面的分析可以看出,Retrofit最重要的點,就是動態(tài)代理,在動態(tài)代理的時候做了很多邏輯處理,簡化我們后面的調(diào)用等等;
下面我們來看最終的總結(jié)流程圖: