1 使用回顧
我們在前面博文《Android網絡編程(十一) 之 Retrofit2框架的使用》中已經對Retrofit的使用進行過介紹。今天我們接着往下來閱讀Retrofit的關鍵源碼從而它進行更加深入的理解。開始前,先來回顧一下簡單的使用,通過使用步驟來深入分析每行代碼背後的原理,代碼如:
// 0 創建一個網絡請求的接口
public interface AppInfoService {
@GET("url.json")
Call<List<AppInfo>> getAppInfoList(@Query("id") int id);
}
private void getRequest() {
// 1 創建 Retrofit 對象,輸入請求URL、轉換器等
Retrofit retorfit = new Retrofit.Builder()
.baseUrl("https://api.xx.com/ ")
.addConverterFactory(GsonConverterFactory.create())
.build();
// 2 通過Retrofit的create創建自定義的請求接口對象
AppInfoService appInfoService = retorfit.create(AppInfoService.class);
// 3 通過調用請求接口方法創建Call對象
Call<List<AppInfo>> call = appInfoService.getAppInfoList(123);
// 4 發起同步或異步的網絡請求
// try {
// Response<List<AppInfo>> response = call.execute();
// List<AppInfo> appInfos = response.body();
// Log.e("zyx", appInfos.toString());
//
// } catch (IOException e) {
// e.printStackTrace();
// }
call.enqueue(new Callback<List<AppInfo>>() {
@Override
public void onResponse(Call<List<AppInfo>> call, Response<List<AppInfo>> response) {
List<AppInfo> appInfos = response.body();
Log.e("zyx", appInfos.toString());
}
@Override
public void onFailure(Call<List<AppInfo>> call, Throwable t) {
Log.e("zyx", t.toString());
}
});
}
可見其步驟大概是:
0 創建一個自定義的網絡請求的接口,裏頭包含請求方式、請求服務端接口名和請求參數的傳入的方法;
1 創建 Retrofit 對象,輸入請求URL、轉換器等;
2 通過Retrofit的create創建自定義的請求接口對象;
3 通過調用請求接口方法創建Call對象;
4 發起同步或異步的網絡請求。
2 原理分析
2.1 創建Retrofit對象
Retrofit對象的創建過程也是使用了構造器模式進行的初始化。首先,Builder方法最終會調用到Platform類的findPlatform方法。
Retrofit.java
public static final class Builder {
// ……
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
}
Platform.java
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
}
上述代碼可見,findPlatform方法內部會根據不同的運行平臺來創建不同的Platform對象。接着調用其build方法。
Retrofit.java
public final class Retrofit {
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
// ……
public Retrofit build() {
// 關鍵代碼1,判斷baseUrl是否爲空
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 關鍵代碼2,獲得或創建 網絡請求執行器工廠 okhttp3.Call.Factory對象
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 關鍵代碼3,獲得或創建回調方法執行器Executor對象
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 關鍵代碼4,創建 網絡請求適配器工廠CallAdapter.Factory列表,
// 並將callAdapterFactories和上面的callbackExecutor對象創建出默認的defaultCallAdapterFactories添加其中
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 關鍵代碼5,創建 數據轉換器工廠Converter.Factory列表
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size() + latform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
// 關鍵代碼6,實例化Retrofit對象
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
}
}
Build方法裏邏輯很清晰,主要就是5件事情:
- 判斷baseurl是否爲空,baseurl的值就是通過. baseUrl方法進行設置。
- 獲得網絡請求執行器工廠callFactory對象值,若爲空,則創建一個OkHttpClient對象,所以很明顯Retrofit默認使用OkHttp進行網絡請求,callFactory的值可通過. client方法進行設置。
- 獲得回調方法執行器callbackExecutor對象值,若爲空,則創建一個默認的,該默認的是一個MainThreadExecutor對象且它內部有一個帶有Looper的Handler,我們後面再來討論它。callbackExecutor的值可通過. callbackExecutor方法進行設置。
- 獲得網絡請求適配器工廠callAdapterFactories的值,將其添加到列表中,callAdapterFactories的值可通過. addCallAdapterFactory方法進行設置。列表創建完後再將關鍵代碼3中的callbackExecutor對象添加其中。
- 創建一個數據轉換器工廠Converter.Factory列表,之後添加內置的數據轉換器BuiltInConverters和默認的數據轉換器工廠defaultConverterFactories,其中還獲得converterFactories的值,也將其添加到列表中,converterFactories的值可通過. addConverterFactory方法進行添加。
- 最後將上述對象傳入Retrofit的構造函數中去實例化Retrofit對象,注意validateEagerly值表示提前驗證,可通過. validateEagerly方法進行設置。
2.2通過Retrofit的create創建自定義的請求接口對象
如示例中代碼 AppInfoService appInfoService = retorfit.create(AppInfoService.class);,Retrofit的create方法是一個泛型的方法,參數就是自定義的接口類型,返回值是一個Proxy.newProxyInstance動態代理對象,請看代碼。
Retrofit.java
public final class Retrofit {
// ……
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
// 關鍵代碼1,是否提前驗證
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 關鍵代碼2,創建一個用於網絡請求接口的動態代理對象並返回
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
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.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 關鍵代碼3,加載網絡請求接口裏的方法,並執行
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
// ……
}
- create方法內首先會判斷validateEagerly變量是否爲true,即是否提前驗證,eagerlyValidateMethods方法其實也就是提前去觸發關鍵代碼3中loadServiceMethod方法邏輯。
- 關鍵代碼2處,此處是創建了一個用於網絡請求接口的動態代理對象,也就是當我們去調用使用回調示例中的AppInfoService的getAppInfoList方法時,最終會調用InvocationHandler的invoke方法。
- 關鍵代碼3處,是加載網絡請求的接口裏的方法並執行,method就是我們自定義的getAppInfoList方法。
2.3通過調用請求接口方法創建Call對象
如示例中代碼Call<List<AppInfo>> call = appInfoService.getAppInfoList(123);,該方法返回一個Call對象,從2.2中得知該方法最終會調用到Retrofit的loadServiceMethod方法返回對象的invoke方法中去,所以我們繼續來看loadServiceMethod方法和invoke方法的代碼。
2.3.1 loadServiceMethod方法
Retrofit.java
public final class Retrofit {
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
// ……
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;
}
// ……
}
loadServiceMethod方法內先從靜態Map對象serviceMethodCache中讀取是否存在之前創建過的網絡請求實例,如果有就直接返回。否則通過ServiceMethod.parseAnnotations方法創建再添加到serviceMethodCache中去最後返回新創建對象。
ServiceMethod.java
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 關鍵代碼1,創建一個請求工廠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.");
}
// 關鍵代碼2,創建HttpServiceMethod對象並返回
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
方法就是做了兩件事情:
- 通過RequestFactory類的parseAnnotations方法創建一個請求工廠。
- 最終創建一個HttpServiceMethod對象並返回。
下面我們繼續來分析RequestFactory的parseAnnotations方法和HttpServiceMethod的parseAnnotations方法邏輯。
2.3.1.1RequestFactory的parseAnnotations方法
RequestFactory.java
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;
final boolean isKotlinSuspendFunction;
RequestFactory(Builder builder) {
method = builder.method;
baseUrl = builder.retrofit.baseUrl;
httpMethod = builder.httpMethod;
relativeUrl = builder.relativeUrl;
headers = builder.headers;
contentType = builder.contentType;
hasBody = builder.hasBody;
isFormEncoded = builder.isFormEncoded;
isMultipart = builder.isMultipart;
parameterHandlers = builder.parameterHandlers;
isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
}
// ……
static final class Builder {
// ……
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
RequestFactory build() {
// ……
return new RequestFactory(this);
}
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);
} 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(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
// ……
}
可見RequestFactory的parseAnnotations方法其實就是傳入Retrofit對象和method參數,然後通過讀取method中定義的註解值(類中的parseMethodAnnotation方法),得到各種網絡請求參數的一個對象。
2.3.1.2 HttpServiceMethod的parseAnnotations方法
獲得RequestFactory對象後,就是作爲參數傳到HttpServiceMethod的parseAnnotations方法去,再看代碼。
HttpServiceMethod.java
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// ……
// 關鍵代碼1,從Retrofit對象中的 網絡請求適配器工廠 獲得 網絡請求適配器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.");
}
// 關鍵代碼2,從Retrofit對象中的 數據轉換器工廠 獲得 數據轉換器 responseConverter
Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
// 關鍵代碼3,從Retrofit對象中的 獲得 網絡請求執行器工廠 callFactory
okhttp3.Call.Factory callFactory = retrofit.callFactory;
// 關鍵代碼4,根據類型創建不同的HttpServiceMethod實現
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);
}
}
// ……
}
HttpServiceMethod的parseAnnotations方法裏會去獲取之前在Retrofit對象中的 網絡請求適配器callAdapter、數據轉換器responseConverter、網絡請求執行器工廠callFactory 以及 通過參數傳入的請求工廠RequestFactory作爲參數,去根據不同類型創建三種分別是CallAdapted,SuspendForResponse和SuspendForBody的HttpServiceMethod對象。其中SuspendForResponse和SuspendForBody是Kotlin suspend 方法的支持,所以我們只看CallAdapted便可以了。
HttpServiceMethod.java
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
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);
}
}
2.3.2 invoke方法
看回上面的 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 代碼,當loadServiceMethod方法返回了ServiceMethod對象後,接着就是調用它的invoke方法。
ServiceMethod.java
abstract class ServiceMethod<T> {
// ……
abstract @Nullable T invoke(Object[] args);
}
invoke方法的實現在HttpServiceMethod類中。
HttpServiceMethod.java
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
// ……
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
}
Invoke方法很簡單,就是調用adapt方法,也就是HttpServiceMethod的實現類CallAdapted中的adapt方法。其代碼已經在上面貼過。這裏請記住第一個參數call是OkHttpCall。
HttpServiceMethod.java
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
//……
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
最終就是 網絡請求適配器callAdapter的adapt方法。
這個網絡請求適配器callAdapter就是在HttpServiceMethod的parseAnnotations方法中關鍵代碼1中,從Retrofit對象中的 網絡請求適配器工廠 獲得的 網絡請求適配器callAdapter。回顧一下上面創建Retrofit對象中的 網絡請求適配器工廠,當時提到該 網絡請求適配器工廠callAdapterFactories的值可通過. addCallAdapterFactory方法進行設置 和 默認的defaultCallAdapterFactories
Platform.java
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(@Nullable Executor callbackExecutor) {
return singletonList(new DefaultCallAdapterFactory(callbackExecutor));
}
DefaultCallAdapterFactory.java
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override public @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
}
最終,如果我們沒有通過. addCallAdapterFactory方法指定callAdapter的話,invoke方法會執行到DefaultCallAdapterFactory類中,所以創建Call對象就是ExecutorCallbackCall對象。
DefaultCallAdapterFactory的ExecutorCallbackCall構造方法接收兩個參數。先說說第二個參數call,我們在HttpServiceMethod的invoke中可知是一個OkHttpCall對象。而第一個參數executor是在創建Retrofit對象時的回調方法執行器callbackExecutor,如果當時不通過.callbackExecutor方法設置的話,它默認是platform.defaultCallbackExecutor();,一個MainThreadExecutor對象,它的源碼如下,可見它內部有一個帶有Looper的Handler。
Platform.java
class Platform {
// ……
static class Android extends Platform {
// ……
@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);
}
}
}
}
2.4發起網絡請求
獲得Call對象後就是最後發請網絡請求。從上面我們得知Call對象就是DefaultCallAdapterFactory.ExecutorCallbackCall,所以無論是異步還是同步的請求,都是調用了DefaultCallAdapterFactory.ExecutorCallbackCall裏的enqueue和execute方法。源碼如下。
DefaultCallAdapterFactory.java
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
// ……
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 Response<T> execute() throws IOException {
return delegate.execute();
}
// ……
}
enqueue和execute方法內都是代理了delegate對象執行,而delegate對象就是OkHttpCall對象。所以我們只看OkHttpCall的enqueue邏輯就會明白了。
OkHttpCall.java
final class OkHttpCall<T> implements Call<T> {
// ……
@Override public void enqueue(final Callback<T> callback) {
// ……
okhttp3.Call call;
// ……
if (call == null && failure == null) {
try {
// 關鍵代碼1,創建okhttp3的call對象
call = rawCall = createRawCall();
} catch (Throwable t) {
// ……
}
}
}
// ……
// 關鍵代碼2,執行call對象的異常請求
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 關鍵代碼3,獲得請求結果進行解析
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
// ……
});
}
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
}
關鍵代碼1中通過createRawCall方法創建了一個okhttp3的call對象,接着在關鍵代碼2中去執行okhttp3的異常請求,然後在關鍵代碼3中通過parseResponse方法進行了請求結果的解析和封裝。最後結果再回調到ExecutorCallbackCall中去,而我們知道okhttp3的回調是執行在子線程中的,在ExecutorCallbackCall也就是MainThreadExecutor對象,因爲它本身帶有Looper的Handler,所以最終將結果回調到主線程中去執行。
同理,同步的方法execute也是調用了okhttp3的call對象的execute方法,最終也是通過parseResponse方法進行了請求結果的解析和封裝。
3 總結
至此,關於Retrofit2框架就介紹完畢,雖然過程中省略了大量的細節,但整體過程原理還是通過源碼瞭解很多。那我們現在用簡短的話來總結一下原理:
第1、創建Retrofit對象,內部先會根據不同的運行平臺來創建不同的Platform對象。然後通過構造器模式進行參數的初始化,如使用:
- 使用baseUrl方法設置要訪問的URL;
- 選擇性使用callFactory方法創建“網絡請求執行器工廠”callFactory,若不使用該方法,則會創建一個OkHttpClient對象;
- 選擇性使用callbackExecutor方法創建“回調方法執行器”callbackExecutor,若不使用該方法,則創建一個默認的defaultCallbackExecutor,它是一個帶Looper的Handler的MainThreadExecutor對象;
- 選擇性使用addCallAdapterFactory方法添加“網絡請求適配器工廠”,以及追加一個默認的網絡請求器DefaultCallAdapterFactory;
- 選擇性使用addConverterFactory方法添加“數據轉換器工廠”中;
- 最後通過上述創建的對象進行實例化Retrofit。
第2、通過Retrofit的泛型方法create並會傳入自定義的接口類型來創建自定義的請求接口對象,該對象是使用了Proxy.newProxyInstance的動態代理對象。
第3、通過調用自定義的請求接口方法創建Call對象,
- 內部先獲取定義方法中的註解值創建一個“請求工廠”RequestFactory,然後再獲取前面Retrofit對象中的“網絡請求適配器”callAdapter、“數據轉換器”responseConverter、“網絡請求執行器工廠”callFactory 以及 剛創建的“請求工廠”RequestFactory,根據類型創建出繼承於HttpServiceMethod的CallAdapted對象;
- 因爲使用了動態代理,所以最後會調用到CallAdapted對象的adapt方法去,又因爲默認的“網絡請求適配器”就是DefaultCallAdapterFactory對象,所以最後adapt方法內部創建的Call對象就是ExecutorCallbackCall對象。
第4、發起網絡請求,就是通過DefaultCallAdapterFactory.ExecutorCallbackCall的enqueue和execute方法來執行異步和同步。這兩個方法都是通過一個OkHttpCall對象來完成,OkHttpCall內部就是封裝了okhttp3的網絡請求。待請求完成後更是將結果回調回到ExecutorCallbackCall裏,再通過帶Looper的Handler的MainThreadExecutor回調方法執行器將結果回調到調用方的主線程中去。