前言
由于是第一次自己翻看源代碼進行學(xué)習(xí),加上基礎(chǔ)不好围橡,在看源代碼的過程中簡直痛苦不堪暖混,但同時也暴露出了自己的許多問題。我覺得學(xué)習(xí)源代碼是一件耗時但也收益頗多的學(xué)習(xí)方式翁授,哪怕你暫時沒有足夠的時間自己去分析學(xué)習(xí)儒恋,也要擅于學(xué)習(xí)別人的經(jīng)驗總結(jié)。
Java 基礎(chǔ)知識點
Retrofit 的功能涉及到了 Java 的『反射』黔漂、『注解』和『動態(tài)代理』诫尽。
公共技術(shù)點之 Java 反射 Reflection
公共技術(shù)點之 Java 注解 Annotation
Retrofit 的主要接口和類
Retrofit 的代碼并不是很多,其底層網(wǎng)絡(luò)通信時交由 OkHttp 來完成的炬守。其包結(jié)構(gòu)如下圖所示:
其中 retrofit2.http 包里面全部是用來定義 HTTP 請求的自定義注解牧嫉。
接口
Call<T>
Call 接口的主要作用是發(fā)送一個 Http 請求,在 Retrofit 中的默認(rèn)實現(xiàn)是 OkHttpCall<T>减途,也可以根據(jù)實際情況實現(xiàn)自己的 Call 類酣藻。Call 實現(xiàn)類需要實現(xiàn)兩個請求發(fā)送方法:
// 同步請求方法,返回請求的結(jié)果
Response<T> execute() throws IOException;
// 異步請求方法鳍置,在 CallBack 中處理返回的結(jié)果
void enqueue(Callback<T> callback);
Callback
Call 的回調(diào)辽剧,該接口是 Retrofit 異步請求數(shù)據(jù)返回的接口,包含兩個方法:
void onResponse(Call<T> call, Response<T> response);
void onFailure(Call<T> call, Throwable t);
Converter
數(shù)據(jù)轉(zhuǎn)換器税产,該接口將 Http 請求返回的數(shù)據(jù)解析成 Java 對象怕轿,我們之前創(chuàng)建 Retrofit實例時有一句:
.addConverterFactory(GsonConverterFactory.create())
就是添加了一個 GsonConverter 來使用 Gson 將我們的結(jié)果轉(zhuǎn)換成 Model 類。
CallAdapter
Call 的適配器辟拷,負(fù)責(zé)將 Call 對象轉(zhuǎn)化成另一個對象撞羽,同樣可在創(chuàng)建 Retrofit 實例時調(diào)用 .addCallAdapterFactory(Factory) 來添加。
Retrofit 執(zhí)行步驟
在上一篇介紹 Retrofit 初步使用的文章里衫冻,已經(jīng)知道 Retrofit 使用的基本步驟诀紊,這里再重新簡單地介紹一遍:
// 創(chuàng)建接口
public interface APIInterface {
@GET("/users/{user}")
Call<TestModel> repo(@Path("user") String user);
}
// 創(chuàng)建 Retrofit 實例
Retrofit retrofit= new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
// 生成接口實現(xiàn)類
APIInterface service = retrofit.create(APIInterface.class);
// 調(diào)用接口實現(xiàn)類的請求方法,獲取 Call 對象
Call<TestModel> model = service.repo("Guolei1130");
// 調(diào)用 Call 對象的異步執(zhí)行方法
model.enqueue(Callback callback)
Retrofit 步驟分析
這里從代碼層面來對上述步驟中的關(guān)鍵進行簡要的分析:
創(chuàng)建 Retrofit 實例隅俘,生成接口的實現(xiàn)類
生成接口實現(xiàn)類時邻奠,編寫了以下語句:
APIInterface service = retrofit.create(APIInterface.class);
.create()的代碼如下所示:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
這里使用了『動態(tài)代理』,返回了一個 Proxy 代理類为居,調(diào)用接口中的任何方法都會調(diào)用 proxy 里的 invoke 方法碌宴。
調(diào)用接口實現(xiàn)類的請求方法,獲取 Call 對象
接著上一步分析颜骤,我們知道當(dāng)我們調(diào)用請求方法時:
Call<TestModel> model = service.repo("Guolei1130");
實際上會調(diào)用到 Proxy 的 invoke 方法唧喉。在該方法內(nèi)捣卤,下面的三行代碼是最為主要和重要的:
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
第一行 loadServiceMethod(method):
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
該方法會根據(jù) 接口請求方法 method 來建造一個 ServiceMethod忍抽,put 到緩存里并返回八孝。在建造 ServiceMethod時,會調(diào)用 createCallAdapter() 來為 ServiceMethod 添加一個 CallAdapter:
// ServiceMethod.Builder(this, method).build();
public ServiceMethod build() {
callAdapter = createCallAdapter();
...
}
// ServiceMethod.createCallAdapter()
private CallAdapter<?> createCallAdapter() {
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.");
}
Annotation[] annotations = method.getAnnotations();
try {
return 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);
}
}
這里會根據(jù) method 的返回類型來創(chuàng)建相應(yīng)的 CallAdapter鸠项,由于 Retrofit 的默認(rèn)實現(xiàn)是 OkHttpCall干跛,所以在這里會創(chuàng)建一個默認(rèn)的 DefaultCallAdapter。至此祟绊,我們再回到 invoke() 的最后一行返回語句:
return serviceMethod.callAdapter.adapt(okHttpCall);
調(diào)用了 DefaultCallAdapter 不對傳進來的 Call 對象做任何處理楼入,所以我們通過調(diào)用接口實現(xiàn)類的方法,實際上最終獲得了一個 OkHttpCall 對象牧抽,其具有兩個請求執(zhí)行方法嘉熊,一個同步,一個異步扬舒。
調(diào)用同步方法時阐肤,會使用應(yīng)用線程來發(fā)送請求;調(diào)用異步方法時會通過 OkHttp 的 Dispatcher 提供的線程來執(zhí)行請求讲坎。
總結(jié)
通過本文孕惜,較為粗糙地從表層了解了 Retrofit 執(zhí)行步驟中一步步在代碼中傳遞的過程,盡管暫時沒能深入代碼內(nèi)部透徹解析各個類和方法晨炕,但是通過這次分析衫画,我自己對 Retrofit 的基本步驟已經(jīng)有了更為深入的了解。
另外這種對框架瓮栗,不能說了如指掌削罩,但對他的實現(xiàn)多了一份認(rèn)識的感覺,真的只有自己去研究過才能體會得到费奸。
也希望各位大神能指出本文中結(jié)構(gòu)或理解上的一些錯誤鲸郊,同時希望這篇文章能幫助您粗略了解 Retrofit 的運行。