ServiceMethod
ServiceMethod時Retrofit中的核心類,之前說的Call捣鲸,CallAdapter.Factory和Convert.Factory纤怒,RequestFactory,Call.Factory都是在ServiceMethod里面的到體現(xiàn)嘹黔。
ServiceMethod是個抽象類,子類類有抽象類HttpServiceMethod涂身,CallAdapted雄卷,SuspendForResponse,SuspendForBody蛤售。具體來看下ServiceMethod和HttpServiceMethod
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//根據(jù)retrofit對象和mathod得到RequestFactory
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
//調(diào)用HttpServiceMethod.parseAnnotations()得到ServiceMethod最終的實現(xiàn)類
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
- 根據(jù)retrofit和method得到RequesrFactory
- 調(diào)用HttpServiceMethod.parseAnnotations()
下面再看下HttpServiceMethod
//解析接口方法上的注釋丁鹉,構(gòu)造出一個可重用的ServiceMethod來用于Http請求
//因為構(gòu)造HttpServiceMethod中需要反射,因此最好每個請求方法只構(gòu)建一次并且可以復用它
//重點是HttpServiceMethod對于每一個請求方法悴能,只構(gòu)建一次揣钦,再次請求相同的方法直接復用之前創(chuàng)建的
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType = Utils.getParameterLowerBound(0,
(ParameterizedType) parameterTypes[parameterTypes.length - 1]);
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// Unwrap the actual body type from Response<T>.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
//構(gòu)造出相應的CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
//構(gòu)造出相應的responseConverter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
//構(gòu)造出相應的okhttp3.Call.Factory
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
- 根據(jù)retrofit上存在的CallAdapter.Factory列表,請求方法method搜骡,方法返回值的類型adapterType拂盯,注解annotations構(gòu)造出相應的CallAdapter
- 根據(jù)retrofit,method记靡,responseType構(gòu)造出responseConverter
- 得到retrofit.callFactory作為自己的callFactory
上面主要是創(chuàng)建請求適配器谈竿,和返回數(shù)據(jù)轉(zhuǎn)換器团驱,我們詳細解析下請求適配器CallAdapter的創(chuàng)建過程,responseConvert的創(chuàng)建跟CallAdapter類似
//調(diào)用retrofit.callAdapter(returnType, annotations)
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
//根據(jù)請求方法的返回類型空凸,返回相應的CallAdapter嚎花,如果沒有合適的CallAdapter,那么就拋異常
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
//因為skipPast為null呀洲,所以初始時start = 0
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
//查找是否有匹配對應返回值的CallAdapter紊选,這里就調(diào)用到CallAdapterFactory中去了
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
//如果沒有合適的CallAdapter,那么拋出異常
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
- 從頭遍歷CallAdapterFactory的列表道逗,找到符合請求返回值的請求適配器CallAdapter兵罢。如果請求的返回值為Observable,那么相應的CallAdapter就是RxJava2CallAdapter滓窍,如果請求返回值為Call卖词,那么就是默認CallAdapter
整體請求流程
前面一篇文章和上面對于ServiceMethod的分析,已經(jīng)對于Retrofit的關(guān)鍵類的作用有了了解吏夯,下面就結(jié)合具體的請求流程此蜈,把上面的類都串起來分析。
Retrofit時采用構(gòu)建者模式構(gòu)造的
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();//緩存ServiceMethod的表
final okhttp3.Call.Factory callFactory;//請求的構(gòu)造工廠噪生,就是OkHttpClient
final HttpUrl baseUrl;//基礎Url
final List<Converter.Factory> converterFactories;//數(shù)據(jù)轉(zhuǎn)換器裆赵,包括請求體,響應體的轉(zhuǎn)換
final List<CallAdapter.Factory> callAdapterFactories;//請求適配器工廠列表
final @Nullable Executor callbackExecutor;//回調(diào)執(zhí)行器
final boolean validateEagerly;//立即驗證標志
可以看到Retrofit最重要的配置就是數(shù)據(jù)轉(zhuǎn)換器和請求適配器跺嗽,并且跟OkHttp強綁定战授。
retrofit最重要的方法就是create(),創(chuàng)建接口請求的實例桨嫁,這里使用動態(tài)代理
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {//如果為true陈醒,那么需要提前驗證請求方法的各個注解,參數(shù)等
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();//支持的平臺瞧甩,在Android 上時Android
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
//調(diào)用的方法是Object的方法,那么就正常調(diào)用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//是否是Platform默認的方法
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//如果都不是上面默認的方法弥鹦,那么就執(zhí)行到這里
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
- 提前驗證的標志默認為false肚逸。如果為true的話,會提前確認好ServiceMethod彬坏,如果緩存中沒有的相應的ServiceMethod朦促,會創(chuàng)建ServiceMethod,并放入緩存
- 如果調(diào)用的方法是Object或者是platform的默認方法栓始,就是不是接口的請求的方法的話务冕,那么就走默認的方法
- 如果不滿足2,那么就確認是接口的請求方法幻赚,此時就會調(diào)用loadServiceMethod禀忆,得到相應的ServiceMethod后調(diào)用invoke(),接下來詳細分析
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;//如果緩存中有臊旭,那么就返回
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
//同步代碼塊,把相應ServiceMethod放入緩存
if (result == null) {
//這里就會調(diào)用ServiceMethod.parseAnnotations()
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
- 檢查緩存中是否有相應的ServiceMethod箩退,如果有的話那么取出來离熏,返回ServiceMethod
- 在同步代碼塊中會再次判斷緩存,如果還是沒有的話戴涝,就會創(chuàng)建ServiceMethod滋戳。這里SreviceMethod對應的是接口里的Method,對于同一個請求方法會復用同一個ServiceMethod啥刻。因為對于同一個方法來說奸鸯,請求適配器CallAdpater,數(shù)據(jù)轉(zhuǎn)換器ResponseConvert可帽,還有參數(shù)的注解娄涩,肯定都是一樣,只是可能每次請求參數(shù)的值不一樣蘑拯。 因為創(chuàng)建ServceMethod用到反射钝满,復用會提高性能。
然后接著調(diào)用loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
invoke()方法是ServiceMethod的抽象方法申窘,真正的實現(xiàn)是在HttpServiceMethod中弯蚜,那么繼續(xù)查看
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);//構(gòu)造出輸入Retrofit的請求OkHttp,內(nèi)部包裝了Okhttp.Call
return adapt(call, args);//adapt()在HttpServiceMethod中是抽象方法
}
- 構(gòu)造出Retrofit.Call 的實現(xiàn)OkHttpCall,內(nèi)部封裝了OkHttp.Call
- 調(diào)用adapt() ,因為HttpServiceMethod的實現(xiàn)類有CallAdapted,SuspendForResponse奏黑,SuspendForBody亏掀,一般都是CallAdapted,所以看下CallAdapted中的實現(xiàn)
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);//調(diào)用了CallAdapter的adaptd()
}
- 調(diào)用了callAdapter的adapt()呀邢,這里我們只追蹤RxJava2CallAdapter中的實現(xiàn)
@Override public Object adapt(Call<R> call) {
//對Retrofit.Call 再封裝,封裝成適配RxJava請求Observable等...
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 RxJavaPlugins.onAssembly(observable);
}
1.在RxJava2CallAdapterFactory 中,默認創(chuàng)建的是同步請求诵叁。即CallExecuteObservable
再看下同步請求CallExecuteObservable,異步請求類似钦椭,不再分析拧额。因為現(xiàn)在大家都對RxJava有一定的了解,所以直接看subscribeActual()
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
//這里執(zhí)行了一次clone()彪腔,因為Call是一次性的請求類型侥锦,所以會為每個Observer創(chuàng)建新的Call
Call<T> call = originalCall.clone();
CallDisposable disposable = new CallDisposable(call);
observer.onSubscribe(disposable);
if (disposable.isDisposed()) {
return;
}
boolean terminated = false;
try {
//執(zhí)行OkHttpCall的同步請求
Response<T> response = call.execute();
if (!disposable.isDisposed()) {
//傳遞給觀察者
observer.onNext(response);
}
if (!disposable.isDisposed()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposable.isDisposed()) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
- 對于OkHttpCall執(zhí)行一次clone(),因為OkHttpCall是一種一次性的類型德挣,只能執(zhí)行一次請求恭垦,所以需要clone(),為每個Observer創(chuàng)建新的請求
- 執(zhí)行OkHttpCall的同步請求,得到Retrofit.Response
- 傳遞給Observer
這時候就串起來了番挺,當調(diào)用請求方法獲得Observable時唠帝,調(diào)用subscribe(),觸發(fā)網(wǎng)絡請求建芙。