Retrofit作為主流的網(wǎng)絡(luò)請(qǐng)求框架掠手,內(nèi)部封裝OkHttp發(fā)起請(qǐng)求锅必,也是聲明式Http客戶(hù)端倒槐,使用接口 + 注解的方式在接口中編寫(xiě)請(qǐng)求方法同窘,前文鋪墊了這么多玄帕,接下來(lái)我們就正式進(jìn)入Retrofit的源碼之旅
網(wǎng)絡(luò)通信流程8步驟&7個(gè)關(guān)鍵成員變量
在解析retrofit的源碼之前,先回顧下retrofit網(wǎng)絡(luò)通信的八步驟想邦,有一個(gè)宏觀的認(rèn)知
網(wǎng)絡(luò)通信8步
- 創(chuàng)建retrofit實(shí)例
- 定義一個(gè)網(wǎng)絡(luò)請(qǐng)求接口并為接口中的方法添加注解
- 通過(guò)動(dòng)態(tài)代理生成網(wǎng)絡(luò)請(qǐng)求對(duì)象裤纹,也就是解析網(wǎng)絡(luò)請(qǐng)求接口中的注解
- 通過(guò)網(wǎng)絡(luò)請(qǐng)求適配器將網(wǎng)絡(luò)請(qǐng)求對(duì)象進(jìn)行平臺(tái)適配(包括Android,Java8,IOS等的)
- 通過(guò)網(wǎng)絡(luò)請(qǐng)求執(zhí)行器發(fā)送網(wǎng)絡(luò)請(qǐng)求
- 通過(guò)數(shù)據(jù)轉(zhuǎn)換器解析數(shù)據(jù)
- 通過(guò)回調(diào)執(zhí)行器切換線程
- 用戶(hù)在主線程處理返回結(jié)果
以上就是Retrofit進(jìn)行網(wǎng)絡(luò)通信的步驟,大致代碼如下所示丧没,相信之前大家已經(jīng)耳熟能詳了
val retrofit = Retrofit.Builder()
.baseUrl("https://www.baidu.com") //請(qǐng)求url地址
.addConverterFactory(GsonConverterFactory.create()) //設(shè)置數(shù)據(jù)解析器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //設(shè)置Rxjava
.build()
val myInterface = retrofit.create(MyInterface::class.java)
val call = myInterface.getCall()
call.execute()
call.enqueue(object : Callback<List<MyResponse>>{
override fun onResponse(
call: Call<List<MyResponse>>,
response: Response<List<MyResponse>>
) {
}
override fun onFailure(call: Call<List<MyResponse>>, t: Throwable) {
}
})
7個(gè)關(guān)鍵成員變量
接下來(lái)我們開(kāi)始看下Retrofit的源碼鹰椒,首先就可以看到它創(chuàng)建了7個(gè)變量,先來(lái)搞清楚這些成員變量的作用,對(duì)之后理解Retrofit通過(guò)動(dòng)態(tài)解析挺有幫助的
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
final List<Converter.Factory> converterFactories;
final List<CallAdapter.Factory> callAdapterFactories;
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
serviceMethodCache
- 它是一個(gè)Map對(duì)象呕童,這里是ConcurrentHashMap對(duì)象漆际,看下它的key值method,也就是http請(qǐng)求的方法夺饲,value值是ServiceMethod灿椅,看到這里有點(diǎn)懵,查閱資料后才知道它代表網(wǎng)絡(luò)請(qǐng)求接口中對(duì)方法進(jìn)行解析钞支,然后解析之后的對(duì)象就是ServiceMethod,相當(dāng)于和注解中的@Get,@Post是成對(duì)出現(xiàn)的操刀,一一對(duì)應(yīng)烁挟;
- 它的作用主要是用于緩存,比如說(shuō)存儲(chǔ)網(wǎng)絡(luò)請(qǐng)求的配置骨坑,還有網(wǎng)絡(luò)請(qǐng)求的方法撼嗓,數(shù)據(jù)轉(zhuǎn)換器,網(wǎng)絡(luò)請(qǐng)求適配器等等
callFactory
- 它是請(qǐng)求網(wǎng)絡(luò)OkHttp的工廠欢唾,由于retrofit默認(rèn)的工廠就是OkhttpClient且警,這個(gè)在之前解析Okhttp的時(shí)候已經(jīng)詳細(xì)提過(guò)了,這里就不贅述了礁遣,這個(gè)工廠的作用就是用于生成我們的OkhttpClient
baseUrl
- 這個(gè)很簡(jiǎn)單了斑芜,就是網(wǎng)絡(luò)請(qǐng)求基礎(chǔ)地址url,有了基地址祟霍,那就有相對(duì)地址杏头,在接口當(dāng)中的相對(duì)地址拼接起來(lái)就是個(gè)完整的url地址
List<Converter.Factory>,List<CallAdapter.Factory>
- 這兩個(gè)都是集合,前者是數(shù)據(jù)轉(zhuǎn)換器工廠的集合沸呐,數(shù) 據(jù)轉(zhuǎn)換器就是對(duì)我們請(qǐng)求之后得到的response進(jìn)行的轉(zhuǎn)換成能用java對(duì)象醇王,總的來(lái)說(shuō)它是用于放置數(shù)據(jù)轉(zhuǎn)換器的工廠;后者是網(wǎng)絡(luò)請(qǐng)求適配器工廠的集合,把Call對(duì)象轉(zhuǎn)換成其他類(lèi)型崭添,比如說(shuō)平臺(tái)想支持Rxjava的話寓娩,就可以轉(zhuǎn)換成Rxjava的Call對(duì)象,就是用于生產(chǎn)CallAdapter,這里簡(jiǎn)單說(shuō)下棘伴,后期需要詳細(xì)說(shuō)明
Executor
- 這是用于執(zhí)行回調(diào)的寞埠,在Android平臺(tái)當(dāng)中,會(huì)看到Platform這個(gè)變量在Retrofit的Builder內(nèi)部類(lèi)中排嫌,默認(rèn)使用MainThreadExecutor主線程池畸裳;其實(shí)我們只要明白,在Retrofit中的網(wǎng)絡(luò)請(qǐng)求最終都是通過(guò)線程池將handler進(jìn)行調(diào)配的淳地,可以處理主線程與子線程的切換;在處理異步的網(wǎng)絡(luò)請(qǐng)求時(shí)就需要它了
validateEagerly
- Boolean類(lèi)型怖糊,這是個(gè)標(biāo)志位,表示的是是否立即解析接口中的方法
Retrofit的Builder內(nèi)部類(lèi)
- Retrofit是通過(guò)建造者模式構(gòu)建出來(lái)的颇象,我們首先看它的Builder內(nèi)部類(lèi)伍伤,是一個(gè)靜態(tài)內(nèi)部類(lèi)
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
....
- 可以看下幾個(gè)成員變量,Platform表示Retrofit適配的平臺(tái)遣钳,默認(rèn)情況都是使用Android平臺(tái)扰魂;callFactory表示的是請(qǐng)求網(wǎng)絡(luò)Okhttp的工廠,默認(rèn)情況下就是OkhttpClient; baseUrl表示網(wǎng)絡(luò)請(qǐng)求url地址蕴茴,需要注意的是這里是HttpUrl劝评,所以需要把String類(lèi)型的url轉(zhuǎn)換為HttpUrl類(lèi)型才能夠被Retrofit使用;convertFactories表示數(shù)據(jù)轉(zhuǎn)換器工廠的集合;adapterFactories表示網(wǎng)絡(luò)適配工廠的集合倦淀;callbackExecutor表示執(zhí)行異步回調(diào)的;validateEagerly表示是否需要立即解析接口中的方法蒋畜,這個(gè)標(biāo)志位用在動(dòng)態(tài)代理要解析定義的注解和方法中,會(huì)進(jìn)行判斷撞叽;
- 回顧這些成員變量和前面介紹地7個(gè)成員變量大體基本是類(lèi)似地姻成,除了PlatForm是Retrofit所沒(méi)有的,所以說(shuō)我們也能看出構(gòu)建者模式就是通過(guò)Builder這個(gè)內(nèi)部類(lèi)進(jìn)行配置愿棋,通過(guò)這個(gè)配置就能把Retrofit當(dāng)中的成員變量初始化
- 接下來(lái)我們查看下Builder類(lèi)的無(wú)參構(gòu)造方法
public Builder() {
this(Platform.get());
}
傳入的是Platform.get(),返回的就是適配平臺(tái)科展,我們可以繼續(xù)看下Platorm內(nèi)部做了什么
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android()
: new Platform(true);
}
private final boolean hasJava8Types;
private final @Nullable Constructor<Lookup> lookupConstructor;
Platform(boolean hasJava8Types) {
this.hasJava8Types = hasJava8Types;
Constructor<Lookup> lookupConstructor = null;
if (hasJava8Types) {
try {
lookupConstructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
lookupConstructor.setAccessible(true);
} catch (NoClassDefFoundError ignored) {
} catch (NoSuchMethodException ignored) {
}
}
this.lookupConstructor = lookupConstructor;
可以看到Platform其實(shí)就是個(gè)單例,它的get方法最終都是調(diào)用findPlatform方法糠雨,根據(jù)不同的運(yùn)行平臺(tái)來(lái)提供不同的線程池才睹;我們看下findPlatform方法中做了什么操作,它其實(shí)就是返回虛擬器所在的那個(gè)平臺(tái),默認(rèn)是在Android平臺(tái)
我們看下這個(gè)Android類(lèi)的代碼
class Android extends Platform {
....
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
//通過(guò)handler post到主線程
handler.post(r);
}
}
- 它這里會(huì)返回一個(gè)默認(rèn)的回調(diào)執(zhí)行器defaultCallbackExecutor甘邀,見(jiàn)名知義砂竖,簡(jiǎn)單來(lái)說(shuō),這個(gè)執(zhí)行器的作用就是用于切換線程鹃答,同時(shí)在主線程中執(zhí)行回調(diào)方法
- 它會(huì)返回一個(gè)MainThreadExecutor(),這個(gè)在下面已經(jīng)初始化好了乎澄,內(nèi)部有個(gè)Handler調(diào)用的是Looper.getMainLooper()這個(gè)靜態(tài)方法,這個(gè)Executor已經(jīng)和主線程(UI線程)綁定了测摔,為了把返回值的處理切換到UI線程, 所以說(shuō)這也是它能夠在主線程回調(diào)方法的原因
- 我們回到Builder內(nèi)部類(lèi)當(dāng)中置济,接下來(lái)我們看下Builder的有參構(gòu)造方法
Builder(Platform platform) {
this.platform = platform;
}
...
這里很簡(jiǎn)單解恰,看到就是將平臺(tái)對(duì)象進(jìn)行賦值給Builder內(nèi)部類(lèi)的成員變量platform,對(duì)于Builder我們?nèi)粘J褂弥型ǔJ褂每諈⑦@個(gè)this(Platform.get())設(shè)置retrofit使用平臺(tái)
以上就是對(duì)Builder的簡(jiǎn)單分析浙于, 總結(jié)以下护盈,它主要是做了以下工作
- 配置平臺(tái)類(lèi)型的對(duì)象Platform,默認(rèn)使用Android
- 配置了網(wǎng)絡(luò)適配和數(shù)據(jù)轉(zhuǎn)換的工廠
- Executor執(zhí)行異步回調(diào)羞酗,這里只是默認(rèn)值的初始化腐宋,還沒(méi)有真正部署到Retrofit的成員變量中
總結(jié)
這部分主要介紹了Retrofit的builder構(gòu)建者模式以及builder內(nèi)部類(lèi)的成員變量的作用,接下來(lái)會(huì)繼續(xù)學(xué)習(xí)分析Retrofit的源碼
未完待續(xù)