標(biāo)簽: Android
先看看這張圖

Retrofit
在學(xué)習(xí)Android的時(shí)候,我最熟悉的網(wǎng)絡(luò)請(qǐng)求框架莫過(guò)于OKHttp + Retrofit,反反復(fù)復(fù)用了很多次,個(gè)人感覺(jué)Retrofit的兼容和解耦做的太好了,這里想要試著分析一下Retrofit的源碼。
RESTful 原則
在我們使用Retrofit這個(gè)框架的時(shí)候,我們都需要后端的接口遵循RESTful原則,那什么是RESTful原則呢?
RESTful是Representational State Transfer的縮寫(xiě),翻譯過(guò)來(lái)就是“表現(xiàn)層狀態(tài)轉(zhuǎn)化”,他是基于HTTP協(xié)議的。
- 表現(xiàn)層:我們?cè)L問(wèn)服務(wù)器是為了“增、刪、改、查”服務(wù)器上面的資源(數(shù)據(jù)),資源的對(duì)應(yīng)的是一段文本(text)、一張圖片、一首歌曲或者一段音頻等,那么這里我們就說(shuō)這些資源的實(shí)體就是表現(xiàn)層。
- 狀態(tài)轉(zhuǎn)化:當(dāng)我們通過(guò)用“增、刪、改、查”的方式訪問(wèn)服務(wù)器的時(shí)候,服務(wù)器的資源實(shí)體可能會(huì)發(fā)生變化,對(duì)應(yīng)的狀態(tài)也會(huì)相映的變化,這就是狀態(tài)轉(zhuǎn)化。
- 客戶端怎么進(jìn)行“增、刪、改、查”? 通過(guò)HTTP協(xié)議,具體就是用HTTP提供的GET、POST、DELETE、PUT的方式。
Retrofit分層
我們導(dǎo)入Retrofit的時(shí)候,發(fā)現(xiàn)我們導(dǎo)入的包分為了三個(gè)部分:包裝OKHttp的Retrofit部分,兼容RxJava的部分和兼容Gson的部分。
一、包裝OKHttp
我們來(lái)看看這個(gè)部分的目錄:

- 首先這里有一個(gè)子目錄http,進(jìn)去看我們就可以發(fā)現(xiàn)里面定義了若干的關(guān)于http協(xié)議的注解(包括GET、POST、PUT和DELETE等)。
- 接下來(lái)就是Retrofit以及它包裝的網(wǎng)絡(luò)請(qǐng)求執(zhí)行器,請(qǐng)求的構(gòu)建器,響應(yīng)、轉(zhuǎn)化器、線程池和工具等等(以上沒(méi)按照順序)
二、兼容Gson
我們來(lái)看看這個(gè)部分的目錄:

這個(gè)部分很簡(jiǎn)單,只包含了三個(gè)部分:Gson轉(zhuǎn)換器的工廠、Gson請(qǐng)求體的轉(zhuǎn)換器和Gson響應(yīng)體的轉(zhuǎn)換器。
三、兼容RxJava
我們?cè)賮?lái)看看這個(gè)部分的目錄:

這個(gè)部分我們可以看到很多繼承自RxJava的Observable對(duì)象,都由RxJava2CallAdapter封裝,最后由它的工廠類(lèi)RxJava2CallAdapterFactory創(chuàng)建出來(lái)。
Retrofit 流程源碼分析
一般情況下我們使用Retrofit的代碼如下:
mApiService = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(BASE_URL)
.client(getClient())
.build()
.create(ApiService.class);
先是通過(guò)Retrofit的構(gòu)建器構(gòu)建一個(gè)Retrofit對(duì)象,前面的幾個(gè)鏈?zhǔn)秸{(diào)用都是為了支持其他三方庫(kù)的功能,我們直接去看Retrofit的構(gòu)建器的build()方法。
Retrofit.Builder.java
//成員
//當(dāng)前的平臺(tái)
private final Platform platform;
//網(wǎng)絡(luò)請(qǐng)求執(zhí)行器的工廠
private @Nullable okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
//可能會(huì)用到的轉(zhuǎn)換器工廠的集合
private final List<Converter.Factory> converterFactories = new ArrayList<>();
//可能會(huì)用到的適配器工廠的集合
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
//可能會(huì)用到的線程池,默認(rèn)為null
private @Nullable Executor callbackExecutor;
//是否在調(diào)用create()方法時(shí),驗(yàn)證傳入的接口中的所有方法
private boolean validateEagerly;
.......
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 制作適配器的防御副本并添加默認(rèn)的呼叫適配器.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 制作轉(zhuǎn)換器的防御副本.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
我們可以看見(jiàn),這里和簡(jiǎn)單的構(gòu)建者模式?jīng)]什么區(qū)別,初始化需要用到的成員變量,然后再直接通過(guò)Retrofit的構(gòu)造函數(shù)創(chuàng)建一個(gè)實(shí)例對(duì)象,接下來(lái)我們?nèi)タ纯碿reate()方法。
public <T> T create(final Class<T> service) {
//驗(yàn)證服務(wù)接口,服務(wù)接口必須是一個(gè)interface對(duì)象,且它沒(méi)有任何父接口
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//通過(guò)動(dòng)態(tài)代理創(chuàng)建服務(wù)接口的實(shí)現(xiàn)類(lèi)
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, @Nullable Object[] args)
throws Throwable {
// 如果是Object的方法,不做任何處理
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//這個(gè)條件判斷在Retrofit3.2.0時(shí)一直為false,其他版本不知道
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//這里通過(guò)服務(wù)接口的方法加載了一個(gè)ServiceMethod對(duì)象
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
在create()方法中,首先驗(yàn)證了我們傳入的服務(wù)接口類(lèi),然后通過(guò)動(dòng)態(tài)代理拿到方法和參數(shù),通過(guò)拿到的方法加載ServiceMethod對(duì)象,那么ServiceMethod是干什么的呢?注釋是這么說(shuō)的:將接口的方法調(diào)整為Http調(diào)用。我們先保留疑問(wèn),去看一下loadServiceMethod()方法做了什么:
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//通過(guò)緩存拿到
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 沒(méi)有緩存就通過(guò)構(gòu)建器構(gòu)建一個(gè)新的ServiceMethod
result = new ServiceMethod.Builder<>(this, method).build();
//緩存
serviceMethodCache.put(method, result);
}
}
return result;
}
這個(gè)方法的干的事情就是,判斷是否有緩存,有就直接返回,沒(méi)有就通過(guò)構(gòu)建器構(gòu)建一個(gè)新的ServiceMethod對(duì)象,這里的緩存是通過(guò)CurrentHashMap,鍵為方法,值為ServiceMethod對(duì)象。這里模擬第一次調(diào)用,沒(méi)有緩存,所以我們器看看ServiceMethod的構(gòu)建器:
Builder(Retrofit retrofit, Method method) {
//配置成員變量
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
//拿到適配器
callAdapter = createCallAdapter();
//通過(guò)響應(yīng)類(lèi)型
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
//拿到轉(zhuǎn)換器
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
- 這里先拿到適配器,判斷適配器的響應(yīng)類(lèi)型是否合法
- 然后再拿到轉(zhuǎn)換器
- 循環(huán)解析——服務(wù)接口中被調(diào)用的方法上的注解
- 檢查各項(xiàng)數(shù)據(jù),new出ServiceMethod實(shí)例
下面我們依次分析這幾步:
第一步: 拿到適配器
private CallAdapter<T, R> createCallAdapter() {
//獲取通用的返回類(lèi)型
Type returnType = method.getGenericReturnType();
//返回類(lèi)型通配符或者變量類(lèi)型
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
//返回類(lèi)型不能是無(wú)返回類(lèi)型
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
//拿到傳入該方法的的注解
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
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);
}
}
這里先是判斷了服務(wù)接口中,被用戶調(diào)用的方法的返回類(lèi)型是否合法,合法之后拿到該方法的注解,轉(zhuǎn)入Retrofit中調(diào)用callAdapter()方法,下面我們?nèi)タ纯催@個(gè)方法:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
這里直接就調(diào)用了nextCallAdapter()方法,我們繼續(xù)跟進(jìn):
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
// 判斷參數(shù)是否為空
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
//找到與傳入?yún)?shù)值相等的變量在List中的索引
int start = adapterFactories.indexOf(skipPast) + 1;
//循環(huán)遍歷找到需要的適配器
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
......
}
這里進(jìn)行了參數(shù)的非空判斷,然后循環(huán)遍歷List,我們看向第十行這里調(diào)用了CallAdapter.Factory的實(shí)現(xiàn)類(lèi)(應(yīng)該是RxJava2CallAdapterFactory)的get()方法,這個(gè)方法會(huì)判斷調(diào)用的服務(wù)接口里面的方法的返回類(lèi)型,是否為Completable、Flowable、Maybe,Single、Obervable,之后會(huì)直接new出來(lái)需要的適配器(Adapter)。
我們?cè)谌タ纯吹诙剑耗玫睫D(zhuǎn)換器
private Converter<ResponseBody, T> createResponseConverter() {
//獲取方法的注解
Annotation[] annotations = method.getAnnotations();
try {
//轉(zhuǎn)到Retrofit中去拿到轉(zhuǎn)換器
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
我們跟到Retrofit中去看看responseBodyConverter()方法怎么拿到轉(zhuǎn)換器的。
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations){
return nextResponseBodyConverter(null, type, annotations);
}
這里和拿到適配器的流程很像,也調(diào)用了一個(gè)nextxxx()方法。
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
//檢查參數(shù)是否為空
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
//獲取參數(shù)的值獲取在List對(duì)應(yīng)的索引
int start = converterFactories.indexOf(skipPast) + 1;
//循環(huán)遍歷,找到轉(zhuǎn)換器
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
......
}
這里可以看見(jiàn),拿到轉(zhuǎn)換器的過(guò)程和拿到適配器的過(guò)程十分相似,重點(diǎn)還是第12行的responseBodyConverter()。根據(jù)我們平時(shí)的用法,這個(gè)方法直接new出來(lái)了一個(gè)GsonResponseBodyConverter(Gson響應(yīng)體轉(zhuǎn)換器)。
我們?nèi)タ纯吹谌剑?解析注解
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
這里解析注解主要有分為兩類(lèi):
- 1 通過(guò)parseHttpMethodAndPath()方法解析出網(wǎng)絡(luò)請(qǐng)求的方法和URL相對(duì)路徑
- 2 通過(guò)parseHeaders()方法解析出——需要添加的請(qǐng)求頭
這里具體的解析方式我們就不深究了。
接下來(lái)我們看看第四步:檢查各項(xiàng)數(shù)據(jù),拿到ParameterHandler,new出ServiceMethod實(shí)例。這里就不挖這些代碼了。
我們回到Retrofit的create()方法:
public <T> T create(final Class<T> service) {
//驗(yàn)證服務(wù)接口,服務(wù)接口必須是一個(gè)interface對(duì)象,且它沒(méi)有任何父接口
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//通過(guò)動(dòng)態(tài)代理創(chuàng)建服務(wù)接口的實(shí)現(xiàn)類(lèi)
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, @Nullable Object[] args)
throws Throwable {
// 如果是Object的方法,不做任何處理
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//這個(gè)條件判斷在Retrofit3.2.0時(shí)一直為false,其他版本不知道
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//這里通過(guò)服務(wù)接口的方法加載了一個(gè)ServiceMethod對(duì)象
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
ServiceMethod的loadServiceMethod()加載完了,接下來(lái)就是直接new出OkHttpCall(網(wǎng)絡(luò)執(zhí)行器),并把OkHttpCall通過(guò)RxJava2CallAdapter的adapt()方法傳過(guò)去,接下里我們看看adapt()方法:
public Object adapt(Call<R> 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;
}
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;
}
首先通過(guò)服務(wù)接口中的方法的返回類(lèi)型中的泛型,判斷被觀察者的種類(lèi)(一般情況下我們都是responseObservable),然后通過(guò)服務(wù)接口中的方法的返回類(lèi)型判斷是Flowable、Single、Maybe或者就是Observable。
到這里我們的Retrofit一套簡(jiǎn)單流程就基本就分析完了,當(dāng)然這里是淺分析,當(dāng)然還有頗多存疑。
mApiService = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(BASE_URL)
.client(getClient())
.build()
.create(ApiService.class);
前面分析總結(jié):create()中使用了動(dòng)態(tài)代理,在實(shí)際調(diào)用服務(wù)接口中的方法時(shí),把方法和參數(shù)傳給了ServiceMethod,ServiceMethod通過(guò)構(gòu)建者模式創(chuàng)建,在build()方法中通過(guò)Retrofit拿到了適配器和轉(zhuǎn)換器,并且對(duì)方法的注解和參數(shù)進(jìn)行了解析,可以說(shuō)ServiceMethod做了很多事情,最后ServiceMethod通過(guò)調(diào)用它拿到的適配器,進(jìn)過(guò)判斷,返回網(wǎng)絡(luò)請(qǐng)求中的被觀察者。
有些童鞋可能會(huì)想,網(wǎng)絡(luò)請(qǐng)求到底是在什么時(shí)候執(zhí)行的呢?
通過(guò)我們拿到的被觀察者,訂閱我們自己寫(xiě)的觀察者時(shí),進(jìn)行的網(wǎng)絡(luò)請(qǐng)求。具體的,RxJava的訂閱方法subscrib()最終會(huì)調(diào)用subscribeActual()這個(gè)方法,這個(gè)方法是個(gè)抽象方法,在Retrofit的取得適配器中的adapt()方法(我們上面分析過(guò)這個(gè)方法)會(huì)new出新的被觀察者,這個(gè)新的觀察者會(huì)覆寫(xiě)subscribeActual()這個(gè)方法,通過(guò)傳入的網(wǎng)絡(luò)執(zhí)行器發(fā)起網(wǎng)絡(luò)請(qǐng)求。
本片文章謝謝童鞋們的觀看。
本人Andorid小白,水平有限,如果有不對(duì)的地方,希望大家提點(diǎn)一下我。