Retrofit原始碼解讀(二)--Retrofit中網路通訊相關
標籤(空格分隔): Retrofit原始碼 學習筆記
前言
- 以下的相關知識總結是通過慕課網的相關學習和自己的相關看法,如果有需要的可以去檢視一下慕課網的相關教學,感覺還可以。
網路通訊八步走
1、建立Retrofit例項 2、定義一個網路請求介面並對介面中的方法新增註解 3、通過 動態代理 生成網路請求物件 4、通過網路請求介面卡,將網路請求物件進行平臺適配 5、通過網路請求執行器,傳送網路請求 6、通過資料轉換器,解析伺服器返回的資料 7、通過回撥執行器,切換執行緒 8、使用者在主執行緒編寫邏輯
建立Retrofit例項
public static Retrofit getRetrofit() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(10, TimeUnit.SECONDS);
return new Retrofit.Builder()
.client(builder.build())
.baseUrl("http://m2.qiushibaike.com/") //設定請求網路地址的url(基地址 這個地址一定要"/"結尾 要不會出現問題)
.addConverterFactory(GsonConverterFactory.create()) //設定資料解析器 預設使用的Gson
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //設定支援RxJava轉換器
.build();
}
複製程式碼
Retrofit的成員變數
//map物件,key值是Method 請求方法,value值是ServiceMethod 主要代表我們的網路請求方法進行註解之後的解析使用
//serviceMethodCache 用於快取網路請求配置,方法,資料轉換器 介面卡
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
//請求網路的okhttp工廠 預設的就是這個
final okhttp3.Call.Factory callFactory;
//請求基地址
final HttpUrl baseUrl;
//資料轉換器工廠集合 用於資料請求得到的response進行轉換
final List<Converter.Factory> converterFactories;
//網路請求介面卡工廠集合 比如RxJava的call
final List<CallAdapter.Factory> adapterFactories;
//回撥執行器 預設的是MainThreadExecutor
final @Nullable Executor callbackExecutor;
//標誌位 是否需要立即解析介面中的方法 後面解析的時候會看到
final boolean validateEagerly;
複製程式碼
Builder內部類
內部類中的成員變數
//平臺 ios android java8
private final Platform platform;
//請求網路的okhttp工廠 預設的就是這個
private @Nullable okhttp3.Call.Factory callFactory;
//請求基地址 需要轉換的
private HttpUrl baseUrl;
//資料轉換器工廠集合 用於資料請求得到的response進行轉換
private final List<Converter.Factory> converterFactories = new ArrayList<>();
//網路請求介面卡工廠集合 比如RxJava的call
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
//回撥執行器 預設的是MainThreadExecutor
private @Nullable Executor callbackExecutor;
//標誌位 是否需要立即解析介面中的方法 後面解析的時候會看到
private boolean validateEagerly;
複製程式碼
可以看到這個內部類的成員變數和retrofit的成員變數是一樣的,因為這個是建造者模式,對於一些的新增的變數和外部類是一樣的。構建者模式就是通過這些配置,將一些成員變數進行初始化
Builder無引數構造方法
public Builder() {
this(Platform.get());
}
可以看出Platform 這個類是個單例 通過findPlatform()方法獲取到這個單例
其中的get()方法就是findPlatform()的方法
在這個方法裡面,通過反射來獲取類名,在安卓中就是返回new Android()
//也就是下方的這個Android類
static class Android extends Platform {
//會有一個預設的回撥執行器MainThreadExecutor Looper.getMainLooper() 也就是主執行緒
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//建立預設的網路請求介面卡工廠 建立預設的網路請求介面卡回撥
//這個預設請求工廠產生的calladapter讓我們的call請求在非同步呼叫的時候會指定我們的Executor執行器 讓他執行回撥
@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);
}
}
}
複製程式碼
Builder有引數構造方法
Builder(Platform platform) {
//做好Platform的初始化
this.platform = platform;
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
//在資料轉換工廠集合中新增一個內建的BuiltInConverters物件 也就是說如果當我們沒有新增或者沒有指定資料轉換工廠(一般會指定為GsonConverterFactory為我們的資料轉換工廠)
converterFactories.add(new BuiltInConverters());
}
複製程式碼
由此我們可以看出來,Builder這個內部類主要是構建了我們的使用平臺,配置了資料轉換器工廠(預設),網路介面卡的工廠,以及我們的Ececutor(預設值的初始化),這個地方還沒有真正的配置到retrofit的成員變數中。
baseUrl(string) 方法
public Builder baseUrl(String baseUrl) {
//工具類檢測我們傳入的url是否為空
checkNotNull(baseUrl, "baseUrl == null");
//通過parse方法將String型別的Url轉換為HttpUrl型別的成員變數
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
//最後通過baseUrl()這個方法來返回Builder這個型別
return baseUrl(httpUrl);
}
//
public Builder baseUrl(HttpUrl baseUrl) {
//判空處理
checkNotNull(baseUrl, "baseUrl == null");
//拆分成多個片段
List<String> pathSegments = baseUrl.pathSegments();
//判斷集合中的最後一個是否以“/”結尾
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
//在這裡可以看出來傳入的url必須以 “/” 結尾
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
複製程式碼
addConverterFactory()方法
/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
我們來看下我們傳入的Factory這個物件GsonConverterFactory
因為我們是通過GsonConverterFactory.create()方法傳入的
public static GsonConverterFactory create() {
//建立Gson物件
return create(new Gson());
}
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
//將傳入的gson物件賦值給我們GsonConverterFactory裡面建立的gson成員變數
this.gson = gson;
}
複製程式碼
addCallAdapterFactory()方法
/**
* Add a call adapter factory for supporting service method return types other than {@link
* Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
我們來看下RxJavaCallAdapterFactory.create()
public static RxJavaCallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJavaCallAdapterFactory(scheduler, false);
}
private RxJavaCallAdapterFactory(Scheduler scheduler, boolean isAsync) {
//主要的是這個Scheduler 用於RxJava中的排程器
this.scheduler = scheduler;
this.isAsync = isAsync;
}
複製程式碼
由此我們可以看出來addConverterFactory()和addCallAdapterFactory()方法很類似,就是建立預設的(我們想要使用的資料轉換器和網路介面卡),並對 converterFactories 、adapterFactories這兩個進行新增資料
build()方法
public Retrofit build() {
//首先判斷baseUrl 這個不能為空
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//這個網路請求執行器 用於產生call 代表實際的http請求
okhttp3.Call.Factory callFactory = this.callFactory;
//如果為空 就會建立一個OkHttpClient 這裡也就是說retrofit預設就是Okhttp作為底層網路請求
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//初始化回撥方法的執行器 用在retrofit非同步請求的時候(同步請求是不需要的) 子執行緒耗時操作-->UI執行緒更新UI
Executor callbackExecutor = this.callbackExecutor;
//如果為空的是 就會建立一個預設的回撥執行器 這個預設的是在platform裡面的預設建立方法 也就是主執行緒的那個
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
//網路請求介面卡集合 將成員變數當中的網路請求介面卡工廠作為引數傳到arraylist的建構函式當中 主要用於配置網路請求介面卡的工廠
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//建立好網路請求介面卡工廠之後 新增我們這個安卓平臺的預設的網路請求介面卡
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
//
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
//這個時候傳入到Retrofit的構造方法中 建立Retrofit物件
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
複製程式碼
這個時候我們簡單的過了建立Retrofit例項的過程,可以通過建造者模式來對相應的數值進行初始化,配置相關的資料轉換器和介面卡,最後通過build方法完成建立Retrofit的例項。