Retrofit是Square公司出品的Http請(qǐng)求框架酵紫,底層網(wǎng)絡(luò)模塊基于Okhttp,是構(gòu)造REST風(fēng)格的HTTP客戶端的利器扒最,同時(shí)具備非常強(qiáng)大的解耦性丑勤,可以自定義多種數(shù)據(jù)格式(xml、json吧趣、protocol buffers等)法竞,支持Rxjava調(diào)用方式除呵。
最近一直在看Retrofit2的源碼,對(duì)于它具體的流程也是在多次調(diào)試后爪喘,才略微一二颜曾。下面主要分析下Rxjava接口形式的接口生成和調(diào)用流程。
Retrofit
Retrofit類是整個(gè)流程的入口通過它的Builder類設(shè)置一些基本的參數(shù)秉剑,如下:
new Builder().baseUrl(baseUrl).addConverterFactory(factory).addCallAdapterFactory(RxJavaCallAdapterFactory.create());
ConverterFactory是Request和Response的轉(zhuǎn)換類泛豪,繼承Factory類,實(shí)現(xiàn)responseBodyConverter和requestBodyConverter即可侦鹏。guava诡曙、gson、java8略水、protobuf等各種格式的converter可以參考官方文檔价卤。
Retrofit#create
通過create(final Class<T> service)方法,將注解定義的接口生成一個(gè)具體的接口實(shí)現(xiàn)渊涝。接口定義方式如下:
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
如果使用Rxjava的話慎璧,可以定義如下:
public interface GitHubService {
@GET("users/{user}/repos")
Observable<List<Repo>> listRepos(@Path("user") String user);
}
具體的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);
}
});
}
它通過Proxy.newProxyInstance方法來一個(gè)實(shí)現(xiàn)了我們定義好的API接口的動(dòng)態(tài)代理類,之后調(diào)用任何接口里面的方法跨释,都會(huì)通過調(diào)用invoke(Object proxy, Method method, Object... args)方法來實(shí)現(xiàn)胸私。
ServiceMethod
invoke方法最重要的是最后三行代碼。loadServiceMethod方法先會(huì)判斷緩存里面有沒有該method對(duì)應(yīng)的ServiceMethod鳖谈,如果有就直接用岁疼,沒有就會(huì)生成一個(gè)新的。
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;
}
下面看下ServiceMethod的生成過程缆娃。
Adapts an invocation of an interface method into an HTTP call.
ServiceMethod 的作用就是把一個(gè) API 方法轉(zhuǎn)換為一個(gè) HTTP 調(diào)用捷绒。
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
以上面的GitHubService中l(wèi)istRepos接口為例。
public interface GitHubService {
@GET("users/{user}/repos")
Observable<List<Repo>> listRepos(@Path("user") String user);
}
@GET("users/{user}/repos"是methodAnnotations贯要,String是parameterTypes暖侨,@Path("user")是parameterAnnotationsArray的第一個(gè),參數(shù)可以有多個(gè)郭毕,所有它是一個(gè)列表它碎。
ServiceMathod#Builder.build()
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
上面是build方法里面去除了異常處理之后的邏輯。
createCallAdapter
private CallAdapter<?> createCallAdapter() {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
return retrofit.callAdapter(returnType, annotations);
}
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;
}
}
它根據(jù)returnType和annotations遍歷adapterFactories显押,獲取合適的CallAdapter。
/** * Returns an instance of {@code T} which delegates to {@code
call}. */ <R> T adapt(Call<R> call);
它的作用就是把 retrofit2.Call<R> 轉(zhuǎn)換成我們需要的 T,目前retrofit2.Call的實(shí)現(xiàn)只有OkHttpCall,所以現(xiàn)在Retrofit網(wǎng)絡(luò)框架只能用OkHttp傻挂。CallAdapters
createCallAdapter
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
return retrofit.responseBodyConverter(responseType,
}
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;
}
}
它最后也是遍歷converterFactories乘碑,獲取合適的ResponseConverter,它一般是自定義的金拒,通過Retrofit的Builder類addConverterFactory(factory)方法添加的兽肤。
parseMethodAnnotation
DELETE套腹、GET、HEAD资铡、PATCH电禀、POST、PUT笤休、OPTIONS這些注解會(huì)調(diào)用parseMethodAnnotation方法尖飞,生成httpMethod、hasBody店雅、relativeUrl政基、relativeUrlParamNames4個(gè)ServiceMethod的參數(shù),當(dāng)注解是retrofit2.http.Headers類型時(shí),會(huì)調(diào)用parseHeaders方法闹啦,它會(huì)生成OkHttp的Headers沮明。
parseParameter
parseParameter方法通過參數(shù)的注解和類型,生成對(duì)應(yīng)的ParameterHandler窍奋。
ParameterAnnotation | ? extends ParameterHandler |
---|---|
Url | RelativeUrl |
Path | Path |
Query | Query |
QueryMap | QueryMap |
Header | Header |
HeaderMap | HeaderMap |
Field | Field |
FieldMap | FieldMap |
Part | Part |
PartMap | PartMap |
Body | Body |
所有類型的ParameterHandler都繼承自ParameterHandler荐健,實(shí)現(xiàn)了apply方法,通過Converter方法琳袄,把參數(shù)都轉(zhuǎn)換成相應(yīng)的類型不瓶,然后設(shè)置到RequestBuilder中厨内,其中Part、PartMap、Body轉(zhuǎn)成RequestBody占婉,其他都轉(zhuǎn)成String。
這樣ServiceMethod基本構(gòu)造完成费尽。
OkHttpCall
之前我們說了至会,它是Retrofit中Call的唯一實(shí)現(xiàn)。
public interface Call<T>
它負(fù)責(zé)發(fā)起請(qǐng)求和回復(fù)矮慕,每個(gè)Call只負(fù)責(zé)一對(duì)請(qǐng)求和回復(fù)帮匾,如果要復(fù)用的話,調(diào)用Call.clone方法痴鳄。Call主要有execute和enqueue方法瘟斜,前者是同步的,后者是異步的痪寻。OkHttpCall實(shí)現(xiàn)了Call接口螺句,里面使用okhttp3.Call來完成網(wǎng)絡(luò)服務(wù)交互。
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; }
createRawCall方法生成okhttp3.Call橡类,request參數(shù)是通過serviceMethod的toRequest方法生成的蛇尚。
execute和enqueue方法里面實(shí)際上就是調(diào)用okhttp3.Call來實(shí)現(xiàn)了同步和異步請(qǐng)求,但是對(duì)Response做了進(jìn)一度處理顾画,通過parseResponse方法取劫,把OkHttp3.Response轉(zhuǎn)成Retrofit2.Response
T body = serviceMethod.toResponse(catchingBody); return
Response.success(body, rawResponse);
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body); }
還是調(diào)用Retrofit里面的responseConverter實(shí)現(xiàn)了返回結(jié)果的轉(zhuǎn)換匆笤。
serviceMethod.callAdapter.adapt(okHttpCall)
這一步是把Call轉(zhuǎn)成我們所需的T。
CallAdapters | ? extends CallAdapter.Factory | T |
---|---|---|
guava | retrofit2.adapter.guava.GuavaCallAdapterFactory | com.google.common.util.concurrent.ListenableFuture |
java8 | retrofit2.adapter.java8.Java8CallAdapterFactory | com.google.common.util.concurrent.ListenableFuture |
rxjava | retrofit2.adapter.rxjava.RxJavaCallAdapterFactory | rx.Observable |
default | retrofit2.ExecutorCallAdapterFactory | retrofit2.Call<R> |
default | retrofit2.DefaultCallAdapterFactory | retrofit2.Call<R> |
如果是retrofit2.Call類型的谱邪,可以調(diào)用execute或者enqueue完成請(qǐng)求炮捧。
如果rx.Observable類型,會(huì)在subscribe()時(shí)候調(diào)用下面代碼:
@Override public void call(final Subscriber<? super Response<T>> subscriber) {
// Since Call is a one-shot type, clone it for each new subscriber.
Call<T> call = originalCall.clone();
// Wrap the call in a helper which handles both unsubscription and backpressure.
RequestArbiter<T> requestArbiter = new RequestArbiter<>(call, subscriber);
subscriber.add(requestArbiter);
subscriber.setProducer(requestArbiter);
}
它其實(shí)是Observable.create(new CallOnSubscribe<>(call))里面CallOnSubscribe的實(shí)現(xiàn)惦银。