上一篇Retrofit源碼解析(一)主要是從Retrofit使用的基本API角度,去理清源碼中大致的流程,可以說Retrofit是對OkHttp框架做了非常完美的封裝,使用了大量的設計模式,使得Retrofit成爲了一個簡單易上手的網絡請求框架. 這一篇主要解決上一篇留下來的疑問.
Retrofit源碼基於版本2.4.0
1.ServiceMethod.Builder類的build函數,調用createCallAdapter函數是怎麼獲取到callAdapter的?
從createCallAdapter函數出發,調用到Retrofit類的callAdapter函數
private CallAdapter<T, R> 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 {
//noinspection unchecked
//遍歷 存放網絡請求適配器工廠的集合callAdapterFactories,找到合適的網絡請求適配器工廠並返回
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);
}
}
callAdapter函數調用nextCallAdapter函數,主要遍歷callAdapterFactories這個存放網絡請求適配器工廠的集合,獲取跟網絡請求函數返回值Call<List< Contributor>>相關的網絡請求適配器工廠,那callAdapterFactories是在哪裏存入適配器工廠? 存入了哪些適配器工廠?
public final class Retrofit {
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");
//遍歷存放網絡請求適配器工廠的集合callAdapterFactories,找到合適的網絡請求適配器工廠調用其get函數並返回CallAdapter實例
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的構造函數中賦值的, 而Retrofit是通過Build模式創建的, 看Retrofit.Builder類的build函數
public final class Retrofit {
public static final class Builder {
public Retrofit build() {
...省略部分無關代碼
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//將MainThreadExecutor裝載進ExecutorCallAdapterFactory工廠實例裏,並將工廠實例添加進 網絡請求適配器工廠的集合裏
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
...省略部分無關代碼
//Collections.unmodifiableList()函數是將集合轉化成只讀的
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
//添加網絡請求適配器
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
}
}
看到callAdapterFactories存入開發者自行添加進去的網絡請求適配器工廠,還存入該平臺默認的網絡請求適配器工廠,此處是Android平臺,對應的網絡請求適配器工廠爲ExecutorCallAdapterFactory, 還記得我們在創建Retrofit時調用了.addCallAdapterFactory(RxJavaCallAdapterFactory.create()),所以此處自行添加的網絡請求適配器工廠是RxJavaCallAdapterFactory.
現在也就找到callAdapterFactories是在Retrofit.Builder的build函數中存入適配器工廠的,存入了兩個適配器工廠,分別是ExecutorCallAdapterFactory和RxJavaCallAdapterFactory.
那上面說的 “獲取跟網絡請求函數返回值Call<List< Contributor>>相關的網絡請求適配器工廠”,獲取到的就應該是ExecutorCallAdapterFactory和RxJavaCallAdapterFactory其中之一
在Retrofit類的nextCallAdapter函數中,通過遍歷callAdapterFactories集合,取出網絡請求適配器工廠並調用自身的get函數,我們看下ExecutorCallAdapterFactory和RxJavaCallAdapterFactory這兩個類的get函數
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
boolean isSingle = rawType == Single.class;
boolean isCompletable = rawType == Completable.class;
//請求函數的返回值必須是 Observable或Single或Completable
//否則返回null
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
if (isCompletable) {
return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
}
}
}
由於我們在上篇文章中寫的網絡請求函數的返回值是 “Call<List< Contributor>>”, 那RxJavaCallAdapterFactory的get函數中getRawType(returnType)拿到的Class類型就是Call,不滿足判斷條件, 所以此處會返回null, 因此不是RxJavaCallAdapterFactory
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
@Override
public 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;
}
//這裏傳入的call = OkHttpCall實例,callbackExecutor = MainThreadExecutor實例
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
}
ExecutorCallAdapterFactory類的get函數中,通過getRawType獲取到的是Call類型,滿足條件,那麼滿足適配器工廠條件的就是ExecutorCallAdapterFactory類,其get函數中創建了CallAdapter的匿名內部類並返回,那此處的匿名內部類實例就是ServiceMethod.Builder類的createCallAdapter函數中retrofit.callAdapter( )獲取到的值,也就是在ServiceMethod.Builder類的build函數調用createCallAdapter函數返回的就是這個匿名內部類
2.ServiceMethod.Builder類的build函數,調用createResponseConverter函數是怎麼生成responseConverter的?
這裏生成的responseConverter的代碼流程跟上面1類似
從createResponseConverter函數出發,調用到Retrofit類的nextResponseBodyConverter函數
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
//遍歷 存放數據轉換器工廠的集合converterFactories,找到合適的數據轉換器工廠並返回
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);
}
}
public final class Retrofit {
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");
//遍歷 存放數據轉換器工廠的集合converterFactories,找到合適的數據轉換器工廠並返回
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;
}
}
...省略無關代碼
}
}
在nextResponseBodyConverter函數中,主要遍歷converterFactories這個存放數據轉換器工廠的集合,獲取跟網絡請求函數返回值Call<List< Contributor>>相關的數據轉換器工廠,那converterFactories在哪裏存入數據轉換器工廠? 存入了哪些數據轉換器工廠?
converterFactories是在Retrofit的構造函數中賦值的, 而Retrofit是通過Build模式創建的, 看Retrofit.Builder類的build函數
public final class Retrofit {
public static final class Builder {
public Retrofit build() {
//...省略無關代碼
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());
//將默認的數據轉換器裝載進工廠實例裏,添加數據轉換器工廠進集合裏
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
//Collections.unmodifiableList()函數是將集合轉化成只讀的
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
//添加數據轉化器工廠
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
}
}
看到converterFactories存入開發者自行添加進去的數據轉換器工廠,還存入該平臺默認的數據轉換器工廠BuiltInConverters類的實例, 還記得我們在創建Retrofit時調用了.addConverterFactory(GsonConverterFactory.create()),所以此處自行添加的數據轉換器工廠是GsonConverterFactory.
現在也就找到converterFactories是在Retrofit.Builder的build函數中存入轉換器工廠的,存入了兩個數據轉換器工廠,分別是BuiltInConverters和GsonConverterFactory.
那上面說的 “獲取跟網絡請求函數返回值Call<List< Contributor>>相關的數據轉換器工廠”,獲取到的就應該是BuiltInConverters和GsonConverterFactory其中之一
在Retrofit類的nextResponseBodyConverter函數中,通過遍歷converterFactories集合,取出數據轉換器工廠並調用自身的responseBodyConverter函數,我們看下BuiltInConverters和GsonConverterFactory這兩個類的responseBodyConverter函數
final class BuiltInConverters extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
}
此處的type就是根據網絡請求函數返回值Call<List< Contributor>> 獲取到的響應數據類型,即type 等於java.util.List<com.example.retrofit.SimpleService$Contributor>,所以BuiltInConverters類的responseBodyConverter函數經過判斷會返回null,顯然不是這個系統默認的數據轉換器工廠
public final class GsonConverterFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
}
根據type等於java.util.List<com.example.retrofit.SimpleService$Contributor>,返回的應該是GsonConverterFactory這個數據轉換器工廠,在其responseBodyConverter函數中返回GsonResponseBodyConverter類的實例,GsonResponseBodyConverter是負責將響應數據轉化爲開發者指定的Java類
因此,在ServiceMethod.Builder類的build函數調用createResponseConverter函數返回的就是GsonResponseBodyConverter類的實例, 即responseConverter就是GsonResponseBodyConverter類的實例
3.OkHttpCall類的createRawCall函數中的call的具體實現類是哪個? 內部怎麼實現的?
final class OkHttpCall<T> implements Call<T> {
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
}
createRawCall函數中的call是通過調用ServiceMethod類的toCall函數生成的,看toCall函數
final class ServiceMethod<R, T> {
okhttp3.Call toCall(@Nullable Object... args) throws IOException {
//...省略無關代碼
//callFactory = OkHttpClient,該OkHttpClient是在Retrofit.Buidler的build函數中進行設置值的
//所以這裏的okhttp3.Call來源於OkHttp.RealCall類的實例
return callFactory.newCall(requestBuilder.build());
}
}
callFactory是在ServiceMethod的構造函數中被賦值,其值來自於Retrofit類,回到Retrofit.Builder類的build函數中
public final class Retrofit {
public static final class Builder {
public Retrofit build() {
//開發者是否傳入OkHttpClient實例,未傳入則創建
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
return new Retrofit(callFactory, baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor,
validateEagerly);
}
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
}
}
callFactory變量就是在此處被初始化的, 在創建Retrofit時,如果開發者未傳入okhttp3.Call.Factory類的實現實例, 則會賦予系統默認的OkHttpClient,所以callFactory實際就是OkHttpClient實例.
接着回到ServiceMethod類的toCall函數,callFactory.newCall() 不就等於OkHttpClient.newCall(), 對OkHttp框架熟悉的話,是不是覺得似曾相似
public class OkHttpClient implements Cloneable, Factory, okhttp3.WebSocket.Factory {
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false);
}
}
那麼OkHttpCall類的createRawCall函數中的call也就是此處生成的RealCall實例. 從這可以看出,OkHttpCall類是通過OkHttp框架來發起異步/同步的請求
4.OkHttpCall類的enqueue函數和execute函數中調用的parseResponse(rawResponse)函數,內部是怎麼解析響應數據的?
final class OkHttpCall<T> implements Call<T> {
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
//根據服務端返回的響應碼進行判斷並處理
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//將響應數據轉化爲 網絡請求函數中定義的返回類型
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
}
看上面的代碼,核心在serviceMethod.toResponse這一句, 接着往下看
final class ServiceMethod<R, T> {
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
}
這裏的responseConverter不就是上面第2個問題中獲取到的GsonResponseBodyConverter類的實例,而GsonResponseBodyConverter內部是用了Gson框架來解析數據.
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();
}
}
}
5.retrofit類create函數中的serviceMethod.adapt是怎麼返回OkHttpCall類的,內部是怎麼實現的?
public final class Retrofit {
public static final class Builder {
public <T> T create(final Class<T> service) {
//檢查網絡請求接口類是不是接口,有沒繼承其他接口 等
Utils.validateServiceInterface(service);
//判斷是否需要提前緩存ServiceMethod對象, validateEagerly默認爲false
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 使用動態代理模式拿到 網絡請求接口類的函數的註解、函數參數、函數返回值等相關信息
// 返回接口調用實例Call,其實這個Call是ExecutorCallbackCall類(Retrofit的Call的實現類)的實例,在後面的代碼中能看到
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 {
// 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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//OkHttpCall是對Retrofit.Call的實現,實際該類主要用到OkHttp.Call(rawCall這個變量) 來進行enqueue、execute請求
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//這裏實際上返回的是ExecutorCallbackCall類(Retrofit的Call的實現類)的實例,看後面的代碼
return serviceMethod.adapt(okHttpCall);
}
});
}
}
}
跟進去ServiceMethod類的adapt函數
final class ServiceMethod<R, T> {
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
}
adapt函數是調用了callAdapter對象的adapt函數,有沒覺得這個callAdapter蠻熟悉的,這不就是上面第1點的callAdapter,它的值就是ExecutorCallAdapterFactory類中get函數中創建的匿名內部類
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
@Override
public 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;
}
//這裏傳入的call = OkHttpCall實例,callbackExecutor = MainThreadExecutor實例
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
}
那麼retrofit類create函數中的serviceMethod.adapt()拿到的就是此處的ExecutorCallbackCall的實例,那ExecutorCallbackCall這個類又有什麼用呢? 這裏多提一個問題,ExecutorCallbackCall是Retrofit框架中很重要的一個類,往下看
6.從上面第5點知道retrofit類create函數中的serviceMethod.adapt()返回的是ExecutorCallbackCall類,這個類有什麼作用?
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
//這裏傳入的delegate = OkHttpCall實例,callbackExecutor = MainThreadExecutor實例
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 = OkHttpCall實例
//OkHttpCall是對Retrofit.Call的實現,實際該類主要用到OkHttp.Call(rawCall這個變量) 來進行enqueue、execute請求
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
//callbackExecutor = MainThreadExecutor, 主要從子線程切換到主線程並返回響應結果
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 {
//這裏的delegate = OkHttpCall實例
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();
}
}
}
看上面的代碼和註釋,ExecutorCallAdapterFactory類主要做了兩件事
-
結合代碼和註釋,調用OkHttpCall類來發起請求,從上面第3點了解到,OkHttpCall類是通過OkHttp框架來發起異步/同步的請求,因此ExecutorCallbackCall類間接調用了OkHttp框架來發起異步/同步的請求
-
MainThreadExecutor把子線程切換到主線程, 將請求OkHttp框架返回的服務端響應數據回調返回