Retrofit對請求方法的解析
Retrofit對我們在接口類中定義的方法是如何轉換成了請求,又如何處理響應。這一切都在它的loadServiceMethod方法中
代碼基于Retrofit2.5.0
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
主要是調用ServiceMethod.parseAnnotations
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);//這里就是對請求的解析,也就是我們定義的接口方法
Type returnType = method.getGenericReturnType();//獲取返回的類型
//省略無關代碼
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
RequestFactory.parseAnnotations這個方法就是對我們定義的接口方法的解析,在里面解析注解和使用反射得到了關于請求的所有信息。
響應的處理
在完成了對請求的處理后構建了RequestFactory類,這個類里面包含了請求的所有信息:
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
private final Method method;
private final HttpUrl baseUrl;
final String httpMethod;
private final @Nullable String relativeUrl;
private final @Nullable Headers headers;
private final @Nullable MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
接下來繼續來看ServiceMethod的parseAnnotations剩下的語句
ServiceMethod.parseAnnotations
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//省略無關代碼
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);//對響應的處理
}
HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);//創建請求適配器
Type responseType = callAdapter.responseType();
//省略無關代碼
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);//創建響應數據轉換器(Gson)
okhttp3.Call.Factory callFactory = retrofit.callFactory;//Okhttp請求客戶端
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
創建請求適配器CallAdapter
首先進入第一行
HttpServiceMethod.createCallAdapter
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method) {
Type returnType = method.getGenericReturnType();//獲取返回的類型
Annotation[] annotations = method.getAnnotations();//獲取注解
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);
}
}
在獲取了方法的返回類型和注解之后,調用
retrofit.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");
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
}
這里面是一個循環獲取請求適配器工廠數組callAdapterFactories,在retrofit創建的時候,我們可以知道往這個數組里面加的是Android平臺默認的ExecutorCallAdapterFactory
public Retrofit build() {
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
}
static class Android extends Platform {
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
//這里可以看到返回的類
ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
}
在剛才的循環里,調用了它的get方法,實際就是調用
ExecutorCallAdapterFactory.get
@Override public @Nullable 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);
}
};
}
我們定義的返回類型一般是泛型的形式,如Call<Response>或者Observable<Response>,所以Utils.getCallResponseType就是取出泛型里面的類型。最后將得到的類型傳入新建的CallAdapter
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
自此就完成了CallAdapter的創建,這里記住它的adapt方法,里面是返回的ExecutorCallbackCall,這個后面會調用,再來繼續看。
HttpServiceMethod的parseAnnotations第一行代碼到此就完了,繼續往下執行:
創建響應數據轉換器(如Gson)和請求客戶端
HttpServiceMethod.parseAnnotations
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();//獲取具體的響應類型
//省略無關代碼
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
注意這里傳給responseConverter的responseType是我們剛才獲取Call泛型里面的具體類型,也就是我們想要拿到的實體類類型。
這個過程跟剛才創建CallAdapter的過程很像,就連方法名都很像,所以來看看createResponseConverter方法:
HttpServiceMethod.createResponseConverter
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
}
通過method的getAnnotations拿到注解列表,然后跟返回類型傳入responseBodyConverter方法:
retrofit.responseBodyConverter
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
int start = converterFactories.indexOf(skipPast) + 1;
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;
}
}
這個過程簡直跟剛才創建CallAdapter的過程一模一樣,也是循環從converterFactories取出Converter,根據之前Retrofit的創建時我們傳入的是GsonConverterFactory,所以是調用的它的responseBodyConverter方法:
GsonConverterFactory.responseBodyConverter
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
這里的代碼就很面熟了,通過TypeToken獲取類型,之后返回一個Gson解析器,它的convert就是調用Gson進行泛型的解析。
GsonResponseBodyConverter
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 {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
到這里就完成了響應字符串的解析器的創建,接下來會執行
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
創建okhttp請求的客戶端,這里命名為callFactory,在Retrofit創建的時候我們傳入的okhttpClient就是賦值給了callFactory,最后將創建好的對象傳入HttpServiceMethod返回。
到此為止就執行完了HttpServiceMethod的parseAnnotations方法,在這個方法里面,創建了幾個重要的東西
- 對請求和響應做具體處理的CallAdapter類,具體為ExecutorCallAdapterFactory,這里要注意它的adapt方法返回ExecutorCallbackCall類
- 響應數據解析工廠Converter,具體為GsonResponseBodyConverter
- okhttp請求客戶端
發送請求
終于到了這一步了,在做好了所有的準備工作之后,最終Retrofit怎么來發送請求呢,首先一步步回到最開始的地方:
在HttpServiceMethod.parseAnnotations方法是在ServiceMethod的parseAnnotations調用的
ServiceMethod.parseAnnotations
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
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.");
}
//在這里調用并返回
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract T invoke(Object[] args);
}
然后ServiceMethod.parseAnnotations方法是在Retrofit的loadServiceMethod調用的
然后loadServiceMethod是在Retrofit的create方法里面創建動態代理的invoke調用的
Retrofit.create
public <T> T create(final Class<T> service) {
//省略無關代碼
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
//省略無關代碼
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
//省略無關代碼
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
可以看到,在loadServiceMethod之后調用了invoke方法,也就是ServiceMethod的invoke方法,點進去之后發現它是個ServiceMethod是個抽象類,它的invoke需要實現類來重寫:
abstract class ServiceMethod<T> {
abstract T invoke(Object[] args);
}
ServiceMethod類只有一個實現類,也就是我們剛才看到過的HttpServiceMethod,所以實際上調用的是它的invoke方法:
HttpServiceMethod.invoke
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
在這里只有一行代碼,實際上是調用callAdapter.adapt,那這個callAdapter是什么呢?剛才我們已經知道它是ExecutorCallAdapterFactory創建的,然后在創建的callAdapter的adapt方法返回ExecutorCallbackCall類,所以來看看這個類:
ExecutorCallbackCall是ExecutorCallAdapterFactory的靜態內部類
ExecutorCallbackCall
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@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);
}
});
}
});
}
@Override public boolean isExecuted() {
return delegate.isExecuted();
}
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
@Override public void cancel() {
delegate.cancel();
}
@Override public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override public Request request() {
return delegate.request();
}
}
在這個類里面,我們就看到了很多很熟悉的方法,enqueue方法發送請求,實際的請求和處理就是在這里面,但是還有疑惑就是具體的處理我們還是沒看到,callbackExecutor和delegate這兩個熟悉才是關鍵所在:
callbackExecutor
這個是在ExecutorCallAdapterFactory的構造方法中傳入的,它的構造方法又是在Platform的defaultCallAdapterFactories方法中調用的,看到Platform,自然可以想到它的Android平臺類,所以這個callbackExecutor實際上是MainThreadExecutor
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
其實代碼很簡單,使用了我們最常用的Handler,讓代碼在主線程中執行,也就是我們通常做的在子線程請求網絡,主線程中更新UI。
delegate
delegate實際是在HttpServiceMethod的invoke方法里傳入:
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
實際上是OkHttpCall這個類,這個類里面就是發送請求和處理響應的具體處理,代碼很多,我們只看看構造方法和enqueue
OkHttpCall(RequestFactory requestFactory, Object[] args,
okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory;//請求工廠,里面包含了請求的所有信息
this.args = args;//參數
this.callFactory = callFactory;//請求客戶端,okhttp
this.responseConverter = responseConverter;//響應的json解析器(Gson)
}
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) {
throwIfFatal(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) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
代碼其實很簡單,就是使用okhttp請求,然后在響應方法onResponse做相應的解析和處理,最后完成網絡請求。
總結
Retrofit對響應的解析大概可分為
- 創建處理適配器CallAdapter,具體實現類為ExecutorCallbackCall,在這里面進行發送請求和處理響應等相關的操作,最終是調用okhttp進行網絡請求
- 創建響應數據轉換器Converter,具體實現類為GsonResponseBodyConverter,用于對返回json數據的解析,這個是我們自己傳入的Gson解析工廠,Retrofit也支持其他的第三方解析庫
- 發送請求,具體的操作類是OkHttpCall來發送請求和處理響應,MainThreadExecutor來做回調的處理,在主線程中處理已經轉化好的實體類。