一廷雅、Retrofit本質流程和相關類
1.具體過程處理如下
- 通過解析 網絡請求接口的注解 配置 網絡請求參數(shù)
- 通過 動態(tài)代理 生成 網絡請求對象
- 通過 網絡請求適配器 將 網絡請求對象 進行平臺適配(平臺包括:Android大溜、Rxjava、Guava和java8)
- 通過 網絡請求執(zhí)行器 發(fā)送網絡請求
- 通過 數(shù)據(jù)轉換器 解析服務器返回的數(shù)據(jù)
- 通過 回調執(zhí)行器 切換線程(子線程 ->>主線程)
- 用戶在主線程處理返回結果
Retrofit在創(chuàng)建實例的時候,會封裝對應的baseUrl僻澎、網絡請求工廠okhttp3.Call.Factory callFactory(其實就是OkHttpClient對象)用來創(chuàng)建okhttp3.Call對象涩盾,在OkHttpCall.enqueue方法中、數(shù)據(jù)轉換器集合List<Converter.Factory> converterFactories用來將對應的數(shù)據(jù)轉換成需要的類型捕捂、回調執(zhí)行器Executor callbackExecutor其實就是將網絡請求從子線程切換到主線程(MainThreadExecutor)
在Retrofit的create方法中瑟枫,會將對應的Service(其實就是interface)通過動態(tài)代理的方式返回一個實例,并且將Service中的方法封裝成ServiceMethod對象指攒,然后通過調用對應的CallAdapter的adapt方法獲取到對應的Call實現(xiàn)類或者Observable對象慷妙,如果是RxJava2的方式,就是獲取到Observable允悦,如果是默認的方式膝擂,就是獲取到對應的Call的實現(xiàn)類ExecutorCallbackCall;
使用RxJava2的方式的時候隙弛,其實就是通過返回的Observable去訂閱觀察者架馋,將Observable的結果通知觀察者,如果是異步的全闷,其實RxJava2CallAdapter返回的就是CallEnqueueObservable叉寂,Observable.subscribe內部就會調用subscribeActual方法,對OkHttpCall這個請求做具體的調用。
2.Retrofit中的類
二、源碼分析(基于Retrofit2.3.0版本)
本文源碼解析是基于Retrofit2.3.0版本吊说,后續(xù)版本略有變化,本文并未做對比钓瞭。但大體邏輯類似
1.創(chuàng)建Retrofit實例
private static Retrofit buildRetrofit() {
return new Retrofit.Builder()
.baseUrl(getBaseUrl())
.client(getOkHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())// Gson工廠,用于將請求結果返回并且解析成Bean對象
.build();
}
這部分我們分成六個步驟腌逢,即:
- new Retrofit
- Builder()
- baseUrl
- addCallAdapterFactory
- addConverterFactory
- build()
(1)步驟1:Retrofit類分析
分析Retrofit類降淮,主要是分析其屬性和用處
public final class Retrofit {
// 網絡請求配置對象(對網絡請求接口中方法注解進行解析后得到的對象)
// 作用:存儲網絡請求相關的配置,如網絡請求的方法、數(shù)據(jù)轉換器佳鳖、網絡請求適配器霍殴、網絡請求工廠、基地址等
// TODO: 這里使用serviceMethodCache這個緩存的目的系吩,其實主要也是反射比較耗費性能来庭,為了節(jié)省性能
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
// 網絡請求器的工廠
// 作用:生產網絡請求器(Call)
// Retrofit是默認使用okhttp
final okhttp3.Call.Factory callFactory;
// 網絡請求的BaseUrl地址
final HttpUrl baseUrl;
// 數(shù)據(jù)轉換器工廠的集合
// 作用:放置數(shù)據(jù)轉換器工廠
// 數(shù)據(jù)轉換器工廠作用:生產數(shù)據(jù)轉換器(converter)
final List<Converter.Factory> converterFactories;
// 網絡請求適配器工廠的集合
// 作用:放置網絡請求適配器工廠
// 網絡請求適配器工廠作用:生產網絡請求適配器(CallAdapter
final List<CallAdapter.Factory> adapterFactories;
// 回調方法執(zhí)行器
final @Nullable Executor callbackExecutor;
// 標志位
// 作用:是否提前對業(yè)務接口中的注解進行驗證轉換的標志位
final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
// unmodifiableList(list)近似于UnmodifiableList<E>(list)
// 作用:創(chuàng)建的新對象能夠對list數(shù)據(jù)進行訪問,但不可通過該對象對list集合中的元素進行修改
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
...// 這里省略其他代碼穿挨,僅看屬性和構造器
}
在Retrofit中月弛,定義了網絡請求器工廠、網絡請求地址科盛、數(shù)據(jù)轉換器工廠帽衙、網絡請求適配器工廠、回調方法執(zhí)行器
CallAdapterFactory作用:
CallAdapterFactory是產生CallAdapter的贞绵,而CallAdapter是網絡請求執(zhí)行器Call的適配器
Call在Retrofit里默認是OkHttpCall
在Retrofit中提供了四種CallAdapterFactory: ExecutorCallAdapterFactory(默認)厉萝、GuavaCallAdapterFactory、Java8CallAdapterFactory榨崩、RxJavaCallAdapterFactory
而CallAdapterFactory的作用:將默認的網絡請求執(zhí)行器(OkHttpCall)轉換成適合被不同平臺來調用的網絡請求執(zhí)行器形式谴垫,如轉換成RxJava2CallAdapterFactory
(2)建造者模式創(chuàng)建Retrofit實例
Retrofit.Builder靜態(tài)內部類
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> adapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
// converterFactories是一個存放數(shù)據(jù)轉換器Converter.Factory的數(shù)組
// 配置converterFactories即配置里面的數(shù)據(jù)轉換器
// BuiltInConverters是一個內置的數(shù)據(jù)轉換器工廠(繼承Converter.Factory類)
// new BuiltInConverters()是為了初始化數(shù)據(jù)轉換器
converterFactories.add(new BuiltInConverters());
}
// 在調用這個Builder構造器的時候,只是對平臺母蛛、網絡請求器的工廠等信息設置了默認值
public Builder() {
this(Platform.get());
}
...// 看Builder的構造器
}
從源碼可以看出翩剪,Builder()其實就做了一件一件事,就是調用帶Platform參數(shù)的構造器彩郊,并且初始化數(shù)據(jù)轉換器前弯。
Platform類
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
// Class.forName(xxx.xx.xx)的作用:要求JVM查找并加載指定的類(即JVM會執(zhí)行該類的靜態(tài)代碼段)
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
// 如果是Android平臺,則返回一個Android對象
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
...
// 用于接收服務器返回數(shù)據(jù)后進行線程切換在主線程顯示結果
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
// 返回一個默認的回調方法執(zhí)行器
// 該執(zhí)行器作用:切換線程(子->>主線程)秫逝,并在主線程(UI線程)中執(zhí)行回調方法
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
// 創(chuàng)建默認的網絡請求適配器工廠
// 該默認工廠生產的 adapter 會使得Call在異步調用時在指定的 Executor 上執(zhí)行回調
// 在Retrofit中提供了四種CallAdapterFactory: ExecutorCallAdapterFactory(默認)博杖、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory
// 采用了策略模式
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
// 獲取與Android 主線程綁定的Handler
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
// 該Handler是上面獲取的與Android 主線程綁定的Handler
// 在UI線程進行對網絡請求返回數(shù)據(jù)處理等操作。
handler.post(r);
}
}
}
}
從Platform.get()方法可以看出,這里是采用一個靜態(tài)內部類對象的單例班巩,platform是在Retrofit.Builder().build()中逊桦,用來初始化回調方法執(zhí)行器和網絡請求適配器工廠
(3)baseUrl()方法
Retrofit的靜態(tài)內部類Builder的baseUrl方法
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
// 創(chuàng)建OkHttp3的HttpUrl對象寺渗,通過解析baseUrl創(chuàng)建
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
// 判斷HttpUrl是否為空
checkNotNull(baseUrl, "baseUrl == null");
// 把URL參數(shù)分割成幾個路徑碎片
List<String> pathSegments = baseUrl.pathSegments();
// 檢測最后一個碎片來檢查URL參數(shù)是不是以"/"結尾
// 不是就拋出異常
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
這里是調用Builder.baseUrl方法炬称,傳入String類型的baseUrl,則會調用參數(shù)類型為HttpUrl的baseUrl對baseUrl進行封裝府蔗,封裝成一個HttpUrl對象
(4)addCallAdapterFactory方法
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
添加網絡請求適配器工廠姓赤,該工廠會返回一個對應的Call對象,然后通過調用MainThreadExecutor的execute()方法,通過對應的Handler切換到主線程。在跟RxJava結合使用的時候,通過調用addCallAdapterFactory方法傳入一個RxJava2CallAdapterFactory實例框仔,用于返回一個RxJava2CallAdapter實例。
(5)addConverterFactory方法
public final class GsonConverterFactory extends Converter.Factory {
<-- 步驟1 -->
public static GsonConverterFactory create() {
// 創(chuàng)建一個Gson對象
return create(new Gson()); ->>步驟2
}
<-- 步驟2 -->
public static GsonConverterFactory create(Gson gson) {
// 創(chuàng)建了一個含有Gson對象實例的GsonConverterFactory
return new GsonConverterFactory(gson); ->>步驟3
}
private final Gson gson;
<-- 步驟3 -->
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
}
GsonConverterFactory.create()是創(chuàng)建了一個含有Gson對象實例的GsonConverterFactory寻馏,并返回給addConverterFactory()
// 將上面創(chuàng)建的GsonConverterFactory放入到 converterFactories數(shù)組
// 在第二步放入一個內置的數(shù)據(jù)轉換器工廠BuiltInConverters()后又放入了一個GsonConverterFactory
// 這是在build之前調用的addConverterFactory方法
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
(6)Retrofit的靜態(tài)內部類Builder的build()
public Retrofit build() {
<-- 配置網絡請求執(zhí)行器(callFactory)-->
okhttp3.Call.Factory callFactory = this.callFactory;
// 如果沒指定宪祥,則默認使用okhttp
// 所以Retrofit默認使用okhttp進行網絡請求
if (callFactory == null) {
callFactory = new OkHttpClient();
}
<-- 配置回調方法執(zhí)行器(callbackExecutor)-->
Executor callbackExecutor = this.callbackExecutor;
// 如果沒指定,則默認使用Platform檢測環(huán)境時的默認callbackExecutor
// 即Android默認的callbackExecutor
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
<-- 配置網絡請求適配器工廠(CallAdapterFactory)-->
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
// 向該集合中添加了步驟2中創(chuàng)建的CallAdapter.Factory請求適配器(添加在集合器末尾)
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 請求適配器工廠集合存儲順序:自定義1適配器工廠藏澳、自定義2適配器工廠...默認適配器工廠(ExecutorCallAdapterFactory)
<-- 配置數(shù)據(jù)轉換器工廠:converterFactory -->
// 在步驟2中已經添加了內置的數(shù)據(jù)轉換器BuiltInConverters()(添加到集合器的首位)
// 在步驟4中又插入了一個Gson的轉換器 - GsonConverterFactory(添加到集合器的首二位)
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
// 數(shù)據(jù)轉換器工廠集合存儲的是:默認數(shù)據(jù)轉換器工廠( BuiltInConverters)耀找、自定義1數(shù)據(jù)轉換器工廠(GsonConverterFactory)、自定義2數(shù)據(jù)轉換器工廠....
// 注:
//1. 獲取合適的網絡請求適配器和數(shù)據(jù)轉換器都是從adapterFactories和converterFactories集合的首位-末位開始遍歷
// 因此集合中的工廠位置越靠前就擁有越高的使用權限
// 最終返回一個Retrofit的對象野芒,并傳入上述已經配置好的成員變量
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
2.創(chuàng)建網絡請求接口實例
(1)如何創(chuàng)建網絡請求接口的實例
不使用RxJava的創(chuàng)建方式
<-- 步驟1:在MainActivity創(chuàng)建接口類實例 -->
AccessApi NetService = retrofit.create(AccessApi.class);
<-- 步驟2:對發(fā)送請求的url進行封裝蓄愁,即生成最終的網絡請求對象 -->
Call<JavaBean> call = NetService.getCall();
(2)分析Retrofit的create方法
Retrofit是通過外觀模式&代理模式狞悲,使用create()方法創(chuàng)建網絡請求接口的實例摇锋,同時通過網絡請求接口里設置的注解進行了網絡請求參數(shù)的配置乖酬。
public <T> T create(final Class<T> service) {
if (validateEagerly) {
// 判斷是否需要提前驗證,默認情況下是false
// 具體方法作用:
// 1. 給接口中每個方法的注解進行解析并得到一個ServiceMethod對象
// 2. 以Method為鍵將該對象存入LinkedHashMap集合中
// 特別注意:如果不是提前驗證則進行動態(tài)解析對應方法(下面會詳細說明)生宛,得到一個ServiceMethod對象施掏,最后存入到LinkedHashMap集合中,類似延遲加載(默認)
eagerlyValidateMethods(service);
}
// 創(chuàng)建了網絡請求接口的動態(tài)代理對象茅糜,即通過動態(tài)代理創(chuàng)建網絡請求接口的實例 (并最終返回)
// 該動態(tài)代理是為了拿到網絡請求接口實例上所有注解
return (T) Proxy.newProxyInstance(
service.getClassLoader(), // 動態(tài)生成接口的實現(xiàn)類
new Class<?>[] { service }, // 動態(tài)創(chuàng)建實例
new InvocationHandler() { // 將代理類的實現(xiàn)交給 InvocationHandler類作為具體的實現(xiàn)(下面會解釋)
private final Platform platform = Platform.get();
// 在 InvocationHandler類的invoke()實現(xiàn)中,除了執(zhí)行真正的邏輯(如再次轉發(fā)給真正的實現(xiàn)類對象)素挽,還可以進行一些有用的操作
// 如統(tǒng)計執(zhí)行時間蔑赘、進行初始化和清理、對接口調用進行檢查等。
@Override
public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// 下面會詳細介紹 invoke()的實現(xiàn)
// 即下面三行代碼
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
在Retrofit.create函數(shù)中使用動態(tài)代理的方式缩赛,對網絡請求接口創(chuàng)建實例耙箍,并且對網絡請求接口中的注解方法做處理
eagerlyValidateMethods類
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) { loadServiceMethod(method); }
// 將傳入的ServiceMethod對象加入LinkedHashMap<Method, ServiceMethod>集合
// 使用LinkedHashMap集合的好處:lruEntries.values().iterator().next()獲取到的是集合最不經常用到的元素,提供了一種Lru算法的實現(xiàn)
}
}
(3)看Retrofit#create中代理模式InvocationHandler類 # invoke()的具體實現(xiàn):
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override
public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// 將詳細介紹下面代碼
// 關注點1
// 作用:讀取網絡請求接口里的方法酥馍,并根據(jù)前面配置好的屬性配置serviceMethod對象
// 這里的method其實就是我們創(chuàng)建的Retrofit的對應接口Service中的每個方法
ServiceMethod serviceMethod = loadServiceMethod(method);
// 關注點2
// 作用:根據(jù)配置好的serviceMethod對象創(chuàng)建okHttpCall對象
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 關注點3
// 作用:調用OkHttp辩昆,并根據(jù)okHttpCall返回rejava的Observe對象或者返回Call
return serviceMethod.callAdapter.adapt(okHttpCall);
}
3.根據(jù)Retrofit.create創(chuàng)建Service的動態(tài)代理進行分析
(1)ServiceMethod serviceMethod = loadServiceMethod(method);
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
// 設置線程同步鎖
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
// ServiceMethod類對象采用了單例模式進行創(chuàng)建
// 即創(chuàng)建ServiceMethod對象前,先看serviceMethodCache有沒有緩存之前創(chuàng)建過的網絡請求實例
// 若沒緩存旨袒,則通過建造者模式創(chuàng)建 serviceMethod 對象
if (result == null) {
// 下面會詳細介紹ServiceMethod生成實例的過程
// ServiceMethod其實就是根據(jù)網絡請求接口中的每個方法創(chuàng)建對應的實例汁针,這個實例保存了
// 網絡請求時所需要的信息,包括網絡請求的適配工廠砚尽,Response轉換器施无,以及請求地址,
// 請求頭必孤,請求body猾骡,請求參數(shù)。而在ServiceMethod中的Builder類中敷搪,保存了一個請求方法
// 的注解解析數(shù)據(jù)兴想、請求參數(shù)類型、請求方法里的參數(shù)的注解內容
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
loadServiceMethod方法主要就是為了創(chuàng)建Service中的方法的ServiceMethod實例赡勘,并且緩存在一個Map集合中嫂便。而ServiceMethod實例中保存了請求這個接口的需要的信息,包括網絡請求工廠狮含、網絡請求適配器顽悼、baseUrl、數(shù)據(jù)轉換器几迄、請求方式蔚龙、相對地址、請求頭映胁、contentType木羹、參數(shù)數(shù)據(jù)以及一些關于是否表達提交、文件提交等解孙。
ServiceMethod類
public final class ServiceMethod {
final okhttp3.Call.Factory callFactory; // 網絡請求工廠
final CallAdapter<?> callAdapter;
// 網絡請求適配器工廠
// 具體創(chuàng)建是在new ServiceMethod.Builder(this, method).build()最后的build()中
// 下面會詳細說明
private final Converter<ResponseBody, T> responseConverter;
// Response內容轉換器
// 作用:負責把服務器返回的數(shù)據(jù)(JSON或者其他格式坑填,由 ResponseBody 封裝)轉化為 T 類型的對象;
private final HttpUrl baseUrl; // 網絡請求地址
private final String relativeUrl; // 網絡請求的相對地址
private final String httpMethod; // 網絡請求的Http方法
private final Headers headers; // 網絡請求的http請求頭 鍵值對
private final MediaType contentType; // 網絡請求的http報文body的類型
private final ParameterHandler<?>[] parameterHandlers;
// 方法參數(shù)處理器
// 作用:負責解析 API 定義時每個方法的參數(shù)弛姜,并在構造 HTTP 請求時設置參數(shù)脐瑰;
// 下面會詳細說明
// 說明:從上面的成員變量可以看出,ServiceMethod對象包含了訪問網絡的所有基本信息
<-- ServiceMethod 類的構造函數(shù) -->
// 作用:傳入各種網絡請求參數(shù)
ServiceMethod(Builder<T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.responseConverter = builder.responseConverter;
this.baseUrl = builder.retrofit.baseUrl();
this.relativeUrl = builder.relativeUrl;
this.httpMethod = builder.httpMethod;
this.headers = builder.headers;
this.contentType = builder.contentType; .
this.hasBody = builder.hasBody; y
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
}
ServiceMethod的Builder類
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
// 獲取網絡請求接口方法里的注釋
this.methodAnnotations = method.getAnnotations();
// 獲取網絡請求接口方法里的參數(shù)類型
this.parameterTypes = method.getGenericParameterTypes();
//獲取網絡請求接口方法里的注解內容
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
ServiceMethod的Builder類的build方法
// 作用:控制ServiceMethod對象的生成流程
<-- 總結 -->
// 1. 根據(jù)返回值類型和方法標注從Retrofit對象的的網絡請求適配器工廠集合和內容轉換器工廠集合中分別獲取到該方法對應的網絡請求適配器和Response內容轉換器廷臼;
// 2. 根據(jù)方法的標注對ServiceMethod的域進行賦值
// 3. 最后為每個方法的參數(shù)的標注進行解析苍在,獲得一個ParameterHandler<?>對象
// 該對象保存有一個Request內容轉換器——根據(jù)參數(shù)的類型從Retrofit的內容轉換器工廠集合中獲取一個Request內容轉換器或者一個String內容轉換器绝页。
public ServiceMethod build() {
// TODO:關注點1
callAdapter = createCallAdapter();
// 根據(jù)網絡請求接口方法的返回值和注解類型,從Retrofit對象中獲取對應的網絡請求適配器
responseType = callAdapter.responseType();
// 根據(jù)網絡請求接口方法的返回值和注解類型寂恬,從Retrofit對象中獲取該網絡適配器返回的數(shù)據(jù)類型
// TODO:關注點3
responseConverter = createResponseConverter();
// 根據(jù)網絡請求接口方法的返回值和注解類型续誉,從Retrofit對象中獲取對應的數(shù)據(jù)轉換器 -->關注點3
// 構造 HTTP 請求時,我們傳遞的參數(shù)都是String
// Retrofit 類提供 converter把傳遞的參數(shù)都轉化為 String
// 其余類型的參數(shù)都利用 Converter.Factory 的stringConverter 進行轉換
// @Body 和 @Part 類型的參數(shù)利用Converter.Factory 提供的 requestBodyConverter 進行轉換
// 這三種 converter 都是通過“詢問”工廠列表進行提供初肉,而工廠列表我們可以在構造 Retrofit 對象時進行添加酷鸦。
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 解析網絡請求接口中方法的注解
// 主要是解析獲取Http請求的方法
// 注解包括:DELETE、GET牙咏、POST臼隔、HEAD、PATCH眠寿、PUT躬翁、
// OPTIONS、HTTP盯拱、retrofit2.http.Headers盒发、Multipart、FormUrlEncoded
// 處理主要是調用方法 parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody)
// ServiceMethod中的httpMethod狡逢、hasBody宁舰、relativeUrl、relativeUrlParamNames域進行賦值
// 獲取當前方法的參數(shù)數(shù)量
int parameterCount = parameterAnnotationsArray.length;
// 創(chuàng)建一個ParameterHandler數(shù)組奢浑,用于保存每個Method中注解值作為key以及參數(shù)值作為value的鍵值對數(shù)據(jù)
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
// 為方法中的每個參數(shù)創(chuàng)建一個ParameterHandler<?>對象并解析每個參數(shù)使用的注解類型
// 該對象的創(chuàng)建過程就是對方法參數(shù)中注解進行解析
// 這里的注解包括:Body蛮艰、PartMap、Part雀彼、FieldMap壤蚜、Field、Header徊哑、QueryMap袜刷、Query、Path莺丑、Url
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
ServiceMethod.Builder.build()中調用了createCallAdapter()方法
private CallAdapter<T, R> createCallAdapter() {
// 獲取網絡請求接口里方法的返回值類型
// 比如Retrofit采用默認的請求ExecutorCallAdapterFactory中的
// 則returnType是Call接口類型著蟹,其實實現(xiàn)類就是ExecutorCallbackCall
// 如果是采用RxJava,則returnType的返回值類型一般就是用Observable
// 參考RxJava2CallAdapterFactory和RxJava2CallAdapter
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
// 獲取網絡請求接口接口里的注解
// 比如@GET或者@POST等
Annotation[] annotations = method.getAnnotations();
try {
// 根據(jù)網絡請求接口方法的返回值和注解類型梢莽,從Retrofit對象中獲取對應的網絡請求適配器
// 下面會詳細說明retrofit.callAdapter()
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
ServiceMethod.Builder.build()中調用了createCallAdapter()方法中返回Retrofit.callAdapter
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
...
// 創(chuàng)建 CallAdapter 如下
// 遍歷 CallAdapter.Factory 集合尋找合適的工廠(該工廠集合在第一步構造 Retrofit 對象時進行添加(第一步時已經說明))
// 如果最終沒有工廠提供需要的 CallAdapter萧豆,將拋出異常
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
}
該方法的目的,就是從Retrofit中的網絡請求適配器工廠集合中昏名,獲取到本網絡請求ServiceMethod對應的網絡請求適配器工廠涮雷。
ServiceMethod.Builder.build()中調用了createResponseConverter()方法
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
// responseConverter 還是由 Retrofit 類提供 -->關注點4
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) {
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
ServiceMethod.Builder.build()中調用了createResponseConverter()方法中返回調用Retrofit.responseBodyConverter方法
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
// 獲取Converter 過程:(和獲取 callAdapter 基本一致)
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
// 遍歷 Converter.Factory 集合并尋找合適的工廠(該工廠集合在構造 Retrofit 對象時進行添加(第一步時已經說明))
// 由于構造Retroifit采用的是Gson解析方式,所以取出的是GsonResponseBodyConverter
// Retrofit - Converters 還提供了 JSON轻局,XML洪鸭,ProtoBuf 等類型數(shù)據(jù)的轉換功能膜钓。
// 繼續(xù)看responseBodyConverter() -->關注點5
}
ServiceMethod.Builder.build()中調用了createResponseConverter()方法中返回調用Retrofit.responseBodyConverter方法中,converterFactories.get(i)可以返回的是GsonConverterFactory卿嘲,這里以GsonConverterFactory為例
Converter.Factory的實現(xiàn)類GsonConverterFactory的responseBodyConverter()
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
// 根據(jù)目標類型,利用 Gson#getAdapter 獲取相應的 adapter
return new GsonResponseBodyConverter<>(gson, adapter);
}
// 做數(shù)據(jù)轉換時調用 Gson 的 API 即可夫壁。
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}
從數(shù)據(jù)轉換適配器的創(chuàng)建過程可以看出拾枣,通過從Retrofit中緩存的數(shù)據(jù)轉換適配器工廠中取出對應的適配器工廠,并且創(chuàng)建對應的數(shù)據(jù)轉換器盒让,而GsonResponseConverter數(shù)據(jù)轉換器的作用梅肤,就是通過Gson和JsonReader轉換數(shù)據(jù),具體轉換參考Gson源碼分析那篇
(2)OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
public class OkHttpCall {
private final ServiceMethod<T> serviceMethod; // 含有所有網絡請求參數(shù)信息的對象
private final Object[] args; // 網絡請求接口的參數(shù)
private okhttp3.Call rawCall; //實際進行網絡訪問的類
private Throwable creationFailure; //幾個狀態(tài)標志位
private boolean executed;
private volatile boolean canceled;
<--OkHttpCall構造函數(shù) -->
public OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
// 傳入了配置好的ServiceMethod對象和輸入的請求參數(shù)
this.serviceMethod = serviceMethod;
this.args = args;
}
(3)return serviceMethod.callAdapter.adapt(okHttpCall);
將創(chuàng)建的OkHttpCall對象傳給創(chuàng)建的ServiceMethod對象中對應的網絡請求適配器工廠的adapt()
返回對象類型:Android默認的是Call<>邑茄;若設置了RxJavaCallAdapterFactory姨蝴,返回的則是Observable<>
從上面部分createCallAdapter的時候,可以知道CallAdapter網絡請求適配器是通過網絡請求適配器工廠的get()方法獲取到的
而默認的網絡請求適配器工廠:ExecutorCallAdapterFactory
如果使用的是RxJava肺缕,則網絡請求適配器工廠為:RxJava2CallAdapterFactory
不使用RxJava的情況-ExecutorCallAdapterFactory的get源碼
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
默認的網絡請求方式左医,其網絡請求適配器是在ExecutorCallAdapterFactory的get中采用返回的,而在return serviceMethod.callAdapter.adapt(okHttpCall);的時候同木,就是調用的這個get方法的CallAdapter實例浮梢,而這個CallAdapter實例的adapt方法其實就是返回的一個ExecutorCallbackCall對象,ExecutorCallbackCall是ExecutorCallAdapterFactory的靜態(tài)內部類彤路,是Call的接口實現(xiàn)類秕硝,實現(xiàn)了異步和同步調用方法,在創(chuàng)建ExecutorCallbackCall對象的時候洲尊,傳入了callbackExecutor和call實例远豺,call其實就是在Retrofit.create中動態(tài)代理中創(chuàng)建的OkHttpCall實例,而callbackExecutor其實就是在Platform實例創(chuàng)建之后坞嘀,在Retrofit.Builder().build()方法中通過platform.defaultCallbackExecutor();賦值
在ExecutorCallbackCall中具體實現(xiàn)異步請求和同步請求的操作的躯护,其實就是在Retrofit.create創(chuàng)建的OkHttpCall實例,并且通過Retrofit創(chuàng)建的callbackExecutor進行線程切換姆吭。ExecutorCallbackCall其實就是將OkHttpCall的委托給ExecutorCallbackCall榛做,由ExecutorCallbackCall調用OkHttpCall執(zhí)行操作。
使用RxJava的方式
如果是使用RxJava的方式内狸,則是使用RxJava2CallAdapterFactory網絡請求適配器工廠检眯,其實get方法如下:
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
這部分就看最后的return,其實返回的就是一個RxJava2CallAdapter實例
RxJava2CallAdapter類
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
private final Type responseType;
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
private final boolean isResult;
private final boolean isBody;
private final boolean isFlowable;
private final boolean isSingle;
private final boolean isMaybe;
private final boolean isCompletable;
RxJava2CallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync,
boolean isResult, boolean isBody, boolean isFlowable, boolean isSingle, boolean isMaybe,
boolean isCompletable) {
this.responseType = responseType;
this.scheduler = scheduler;
this.isAsync = isAsync;
this.isResult = isResult;
this.isBody = isBody;
this.isFlowable = isFlowable;
this.isSingle = isSingle;
this.isMaybe = isMaybe;
this.isCompletable = isCompletable;
}
@Override public Type responseType() {
return responseType;
}
@Override public Object adapt(Call<R> call) {
// 執(zhí)行網絡請求昆淡,在這里是創(chuàng)建了Observable
// 然后就采用RxJava的觀察者模式锰瘸,CallEnqueueObservable其實就是一個被觀察者
// 在Observable訂閱觀察者的時候,就會在subscribe內部調用
// CallEnqueueObservable的subscribeActual函數(shù)
// 在subscribeActual函數(shù)中調用了call.enqueue這個Http.Call的異步調用
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
// 如果是使用RxJava2的方式昂灵,則調用Observable的subscribeOn方法
// 其內部就調用了對應的Observable的subscribeActual方法
// 在Observable的subscribeActual方法內部就會調用對應的OkHttpCall的enqueue方法執(zhí)行請求
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
}
在這里返回的Observable其實就是通過是否異步來判斷返回的CallEnqueueObservable或者CallExecuteObservable對象避凝。
CallEnqueueObservable中的subscribeActual方法
CallExecuteObservable的subscribeActual方法與之類似舞萄,只不過CallExecuteObservable的subscribeActual方法內部是調用了OkHttpCall的execute()方法
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
...
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
call.enqueue(callback);
}
...
}
這里的Call,其實就是在Retrofit.create中的動態(tài)代理中創(chuàng)建的OkHttpCall對象管削,而在CallEnqueueObservable中的subscribeActual方法中倒脓,通過OkHttpCall對象調用enqueue執(zhí)行請求,而在OkHttpCall.enqueue方法中含思,就會通過OkHttpCall的createRawCall()方法崎弃,通過okhttp3.Call.Factory callFactory對象創(chuàng)建okhttp3.Call對象,用來執(zhí)行網絡請求含潘。所以okhttp3.Call.Factory callFactory目的就是用來創(chuàng)建OkHttp3.Call饲做。而在OkHttpCall對象調用enqueue方法中,會轉換返回結果遏弱,而解析返回結果其實就是通過ServiceMethod.toResponse方法盆均,這個方法中轉換返回結果其實就是借助轉換器responseConverter
OkHttpCall.createRawCall()
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
Observable.subscribe方法
@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Disposable has been set or not
// can't call onSubscribe because the call might have set a Subscription already
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
在RxJava2CallAdapter的adapt方法中,會創(chuàng)建Observable被觀察者漱逸,如果是異步的泪姨,則CallEnqueueObservable對象,如果是同步的CallExecuteObservable對象虹脯。
而CallEnqueueObservable和CallExecuteObservable類都是Observable的子類驴娃,都重寫了subscribeActual,subscribeActual方法是Observable調用subscribe方法訂閱觀察者的時候調用的循集。而具體的網絡請求就是在subscribeActual中執(zhí)行唇敞。
(4)總結
Retrofit采用了 外觀模式 統(tǒng)一調用創(chuàng)建網絡請求接口實例和網絡請求參數(shù)配置的方法,具體細節(jié)是:
動態(tài)創(chuàng)建網絡請求接口的實例(代理模式 - 動態(tài)代理)
創(chuàng)建 serviceMethod 對象(建造者模式 & 單例模式(緩存機制))
對 serviceMethod 對象進行網絡請求參數(shù)配置:通過解析網絡請求接口方法的參數(shù)咒彤、返回值和注解類型疆柔,從Retrofit對象中獲取對應的網絡請求的url地址、網絡請求執(zhí)行器镶柱、網絡請求適配器 & 數(shù)據(jù)轉換器旷档。(策略模式)
對 serviceMethod 對象加入線程切換的操作,便于接收數(shù)據(jù)后通過Handler從子線程切換到主線程從而對返回數(shù)據(jù)結果進行處理(裝飾模式)
(5)采用RxJava+Retrofit的總結
最終的網絡請求歇拆,是在serviceMethod.callAdapter.adapt(okHttpCall);調用的時候鞋屈,通過serviceMethod.callAdapter其實是在serviceMethod.Builder().build()的時候,調用createCallAdapter通過從Retrofit.callAdapter中故觅,從adapterFactories獲取到對應的CallAdapterFactory厂庇,然后再對應的CallAdapterFactory的get方法中返回對應的CallAdapter,然后再調用CallAdapter的adpt函數(shù)输吏,在這里進行最終的網絡請求返回Observable权旷,在RxJava2CallAdapter的adpt函數(shù)中會通過判斷是否是異步返回對應的Observable
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
在拿到這個Observable之后,CallEnqueueObservable的subscribeActual會調用Call的對應請求方法贯溅,如果是同步的就調用call.execute();如果是異步的就調用你call.enqueue(callback);
這個調用在Observable.subscribe訂閱觀察者的時候會觸發(fā)拄氯,這樣就執(zhí)行了網絡請求躲查。
創(chuàng)建ServiceMethod對象,是為了配置對應的數(shù)據(jù)译柏,比如網絡請求工廠镣煮、網絡請求適配器、Response內容轉換器鄙麦、請求地址怎静、請求方法、請求頭黔衡、ContentType、請求參數(shù)腌乡、方法注解和參數(shù)注解
(6)采用普通方式的總結
如果不是用的RxJava盟劫,那么網絡請求工廠去獲取網絡請求適配器的時候,是用ExecutorCallAdapterFactory這個工廠与纽,其get函數(shù)返回一個CallAdapter匿名內部類實現(xiàn)侣签,然后這個CallAdapter的adpt函數(shù)會返回ExecutorCallbackCall對象,這個對象就是OkHttp3.Call的子類
如果是返回的Okhttp3.Call急迂,那么就需要手動的觸發(fā)execute或者enqueue
4.執(zhí)行網絡請求
這里針對OkHttpCall的使用源碼做一定的分析
不管是使用普通方式還是RxJava方式影所,網絡請求均是使用OkHttpCall來實現(xiàn)。
Retrofit默認使用OkHttp僚碎,即OkHttpCall類(實現(xiàn)了 retrofit2.Call<T>接口)
OkHttpCall提供兩種網絡請求方式:
同步請求:OkHttpCall.execute()
異步請求:OkHttpCall.enqueue()
比如采用非RxJava的形式實現(xiàn)網絡請求的時候猴娩,Retrofit.create方法會返回一個默認的Call接口實現(xiàn)類,而這個默認的接口實現(xiàn)類對象其實就是ExecutorCallbackCall對象勺阐,是ExecutorCallAdapterFactory的內部類卷中,是對OkHttpCall的封裝代理,
static final class ExecutorCallbackCall<T> implements Call<T> {
// 線程切換執(zhí)行器渊抽,默認的是MainThreadExecutor對象蟆豫,
// 是咋Platform類中的
final Executor callbackExecutor;
// 代理OkHttpCall類
final Call<T> delegate;
...
(1)同步請求OkHttpCall.execute()
其實采用非RxJava2對象的話,則是調用ExecutorCallbackCall的execute()懒闷,而ExecutorCallbackCall的execute()其實就是調用了OkHttpCall的execute()
這是OkHttpCall的execute()方法
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
// 設置同步鎖
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
// 步驟1:創(chuàng)建一個OkHttp的Request請求對象 -->關注1
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
// 步驟2:調用OkHttpCall的execute()發(fā)送網絡請求(同步)
// 步驟3:解析網絡請求返回的數(shù)據(jù)parseResponse() -->關注2
return parseResponse(call.execute());
}
針對上面的這三步十减,做進一步的分析
call = rawCall = createRawCall();
創(chuàng)建Http請求對象,其實就是Okhttp3.Call實現(xiàn)類對象愤估,其實就是OkHttp3的RealCall對象帮辟。
private okhttp3.Call createRawCall() throws IOException {
// 從ServiceMethod的toRequest()返回一個Request對象
Request request = serviceMethod.toRequest(args);
// 根據(jù)serviceMethod和request對象創(chuàng)建 一個okhttp3.Request
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
return parseResponse(call.execute());
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
// 這里就是Retrofit執(zhí)行網絡請求之后返回的結果,返回的body其實是stream
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
// 內部調用responseConverter.convert(body);
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
在使用Retrofit的時候需要特別注意:
ServiceMethod幾乎保存了一個網絡請求所需要的數(shù)據(jù)
發(fā)送網絡請求時灵疮,OkHttpCall需要從ServiceMethod中獲得一個Request對象
解析數(shù)據(jù)時织阅,還需要通過ServiceMethod使用Converter(數(shù)據(jù)轉換器)轉換成Java對象進行數(shù)據(jù)解析。其實Retrofit的OkHttpCall就是在create中創(chuàng)建的OkHttpCal對象
(2)異步請求:OkHttpCall.enqueue()
發(fā)送請求過程
步驟1:對網絡請求接口的方法中的每個參數(shù)利用對應ParameterHandler進行解析震捣,再根據(jù)ServiceMethod對象創(chuàng)建一個OkHttp的Request對象
步驟2:使用OkHttp的Request發(fā)送網絡請求荔棉;
步驟3:對返回的數(shù)據(jù)使用之前設置的數(shù)據(jù)轉換器(GsonConverterFactory)解析返回的數(shù)據(jù)闹炉,最終得到一個Response<T>對象
步驟4:進行線程切換從而在主線程處理返回的數(shù)據(jù)結果
OkHttpCall.enqueue
如果是異步請求,則需要先調用ExecutorCallbackCall的enqueue方法润樱,然后在ExecutorCallbackCall的enqueue方法中調用OkHttpCall的enqueue方法渣触,而這里的callback回調,就是在ExecutorCallbackCall中實現(xiàn)的時候使用了callbackExecutor進行線程切換壹若。
先看ExecutorCallbackCall的enqueue()方法
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
再看OkHttpCall的enqueue方法
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
這里如果是不使用RxJava嗅钻,則采用的是默認的ExecutorCallAdapterFactory網絡請求適配器工廠,那么就會先調用ExecutorCallbackCall的enqueue方法店展,然后在獲取到請求結果之后通過callbackExecutor進行網絡請求的線程切換养篓。
而ExecutorCallbackCall的enqueue方法中調用了delegate.enqueue方法,這個方法其實就是調用的OkHttpCall的enqueue方法赂蕴。ExecutorCallbackCall其實就是對OkHttpCall的一個封裝柳弄,采用委托模式。
使用RxJava2的網絡請求概说,在網絡請求適配器的adapt方法時有請求的不同:
而如果是使用了RxJava2CallAdapterFactory工廠碧注,那么在Retrofit.create方法中就會通過動態(tài)代理返回RxJava2CallAdapter的adapt方法,而在RxJava2CallAdapter的adapt方法中糖赔,會通過判斷是否是異步來執(zhí)行不同的網絡請求萍丐,返回Observable結果:
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
如果是異步的,就會創(chuàng)建CallEnqueueObservable對象
然后通過判斷是否是需要返回的body還是result來封裝成不同的Observable
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
這里的Observable是一個被觀察者對象放典,因為使用了RxJava2的時候逝变,會將Observable被觀察者對象訂閱一個觀察者,調用Observable的subscribe方法奋构,在這個方法里調用被觀察者的subscribeActual方法骨田。
這時,就會優(yōu)先調用ResultObservable的subscribeActual方法声怔,
@Override protected void subscribeActual(Observer<? super Result<T>> observer) {
upstream.subscribe(new ResultObserver<T>(observer));
}
然后在這個方法內部調用CallEnqueueObservable的subscribeActual方法态贤,
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
call.enqueue(callback);
}
在這里執(zhí)行異步請求任務,然后將結果返回給觀察者醋火。