Android小知識-剖析Retrofit中的網路請求流程以及相關引數
本平臺的文章更新會有延遲,大家可以關注微信公眾號-顧林海,包括年底前會更新kotlin由淺入深系列教程,目前計劃在微信公眾號進行首發,如果大家想獲取最新教程,請關注微信公眾號,謝謝!
在使用Retrofit時,需要建立Retrofit的例項,定義一個網路請求介面併為介面中的方法添加註解,接著通過動態代理生成網路請求物件,關於動態代理的介紹可以檢視 ofollow,noindex">《Android小知識-剖析Retrofit前的預備知識(靜態代理與動態代理)》 ,在Retrofit中會去解析在網路請求介面中的註解,並配置網路請求引數,通過動態代理攔截生成網路請求物件。
內部通過網路請求介面卡將網路請求物件進行平臺適配,比如Android或Java8, 接著通過網路請求執行器傳送網路請求,這個網路請求執行器就是Call,這個Call就是對OkHttp的一個封裝,底層還是使用OkHttp來發送請求的,服務端返回的資料會經過資料轉換器進行解析,在《 Android小知識-Retrofit框架的介紹以及使用方式 》章節中,使用的是GsonConverter來解析資料,最終轉換成Java物件,接著通過回撥執行器切換執行緒,最後客戶端在主執行緒處理返回的結果。
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://icould.glh/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); 複製程式碼
上面建立Retrofit的例項在《 Android小知識-Retrofit框架的介紹以及使用方式 》中已經講過了,建立Retrofit例項採用的是構建者模式,構建者模式可以將一個物件的複雜構建與表示進行分離,我們進入Retrofit的原始碼。
public final class Retrofit { 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; ... } 複製程式碼
在具體分析原始碼前,我們有必要了解Retrofit的幾個成員變數。
serviceMethodeCache是一個LinkedHashMap物件,它的key值是Method,對應的就是Http的請求方法,value是ServiceMethod,ServiceMethod是對網路請求介面內的方法的註解進行解析封裝後的物件。
callFactory是網路請求工廠,在Retrofit內預設的網路請求工廠採用的就是OkHttpClient。
baseUrl就是網路請求的URL的基地址,baseUrl加上網路請求介面中通過註解定義的相對地址,就組成了一個完整的請求地址。
converterFactories是資料轉換器工廠集合,內部存放的是資料轉換器工廠,而資料轉換器工廠是用於生產資料轉換器,資料轉換器的作用就是對請求網路之後的Response進行轉換,通過GsonConverter轉換成Java物件。
adapterFactories是網路請求介面卡工廠集合,內部存放的是網路請求介面卡工廠,網路介面卡工廠是用生產網路介面卡,網路請求介面卡的作用就是將Call物件轉換成其他型別,如果需要支援RxJava,就可以將Call物件轉換成RxJava平臺的Call。
callbackExecutor是一個執行緒池,用於執行回撥的執行緒池。
validateEagerly是一個標誌位,是否需要立即解析介面中的方法,具體後面進行講解,這裡先有個印象。
Retrofit的7個成員變數介紹完了,接著進入Retrofit的Builder類:
public final class Retrofit { ... public static final class Builder { private final Platform platform; private @Nullable okhttp3.Call.Factory callFactory; private 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類是Retrofit的靜態內部類,成員變數platform表示Retrofit適配的平臺,主要包括Android和Java 8,預設情況下使用的是Android平臺;callFactory表示請求網路的OkHttp的工廠,預設情況下使用OkHttp來完成請求;baseUrl表示網路請求的URL,通過Builder的baseUrl方法傳入一個String型別的url,再將String型別的url轉換成HttpUrl;converterFactories是資料轉換器工廠的集合;callAdapterFactories是網路請求介面卡工廠的集合;callbackExecutor用執行非同步回撥;validateEagerly是一個標誌位,表示是否需要立即解析介面中的方法,在使用動態代理時對網路請求介面中方法的註解進行解析時會用到這個標誌位。
public final class Retrofit { ... public static final class Builder { public Builder() { this(Platform.get()); } ... } ... } 複製程式碼
在Builder的建構函式中通過this傳入一個Platform型別,也就是適配的平臺,進入Platform的get方法:
private static final Platform PLATFORM = findPlatform(); static Platform get() { return PLATFORM; } private static Platform findPlatform() { try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { return new Android(); } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); } 複製程式碼
Platform是一個單例類,通過findPlatform方法來初始化例項,在靜態方法get中返回了PLATFORM靜態變數,而PLATFORM靜態變數的初始化是在findPlatform方法中完成的,在findPlatform方法中先是通過反射載入"android.os.Build"類,接著返回一個Android平臺的Platform物件,我們看一下這個Android物件。
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } } 複製程式碼
在defaultCallbackExecutor中返回一個MainThreadExecutor物件,表示預設的回撥方法執行器,這個執行器的作用是從子執行緒切換到主執行緒,看下面MainThreadExecutor實現了Executor,是一個執行緒池,並且內部在建立Handler時傳入的是主執行緒的Looper,通過Looper.getMainLooper()獲取主執行緒Looper,也就是說這個Executor和主執行緒已經綁定了。繼續看Android類中的defaultCallAdapterFactory方法,它表示建立一個預設的網路請求介面卡工廠的執行器,在Call物件執行非同步請求時,需要一個執行器將非同步請求後的資料傳遞到主執行緒,defaultCallAdapterFactory放內傳入的就是非同步請求時進行資料傳遞所需要的執行器。
在Builder的無參構造方法內呼叫了有參構造方法:
Builder(Platform platform) { this.platform = platform; } 複製程式碼
將建立好的Android平臺Platform物件賦值給Builder類的成員變數platform。
Builder的相關成員變數的初始化已經介紹完畢,接著看看它的build方法:
public Retrofit build() { ... //建立OkHttpClient的工廠 okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } //建立主執行緒執行器 Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } //新增網路請求介面卡工廠 List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); //新增資料轉換器工廠 List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size()); converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this.converterFactories); //建立Retrofit例項 return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); } 複製程式碼
build方法中的註釋已經很詳細了,判斷callFactory是否為空,如果為空,預設建立OkHttpClient,這也說明了Retrofit內部預設是使用OkHttp來進行網路請求的;callbackExecutor預設通過platform的defaultCallbackExecutor方法獲取執行器,這裡的platform預設是Android平臺,在前面講解Android平臺類時,就已經知道了它的defaultCallbackExecutor方法返回的是主執行緒的執行器,最終資料就是通過主執行緒的執行器傳送到主執行緒的。
建立完主執行緒的執行器後,新增網路請求介面卡工廠,這裡添加了Android平臺的defaultCallAdapterFactory方法傳入主執行緒的執行器,這樣在進行非同步請求後可以通過主執行緒的執行器進行資料傳遞。
最後就是新增資料轉換器工廠,預設添加了一個BuiltInConverters物件,BuiltInConverters表示的是內建的預設的資料轉換器工廠。

搜尋微信“顧林海”公眾號,定期推送優質文章。