Retrofit源碼結構
Retrofit: 通過註解,把一個Java接口轉化成一個http 請求,底層網絡請求基於okhttp
從Retrofit源碼結構可以看出,Retrofit 源碼分成兩部分
一部分是包retrofit2.http裏面的,在Java接口方法中使用,用來控制http行爲的註解。
一部分是retrofit2裏面的,負責把REST API轉化成Java接口。
Retrofit和okhttp的關係
retrofit依賴okhttp庫,retrofit 所有的網絡請求都是由okhttp處理,可以說retrofit是對okhttp封裝了,讓其使用更加簡單方便。
okhttp 準確來說是一個Java庫,沒有Android中主線程和工作線程的概念,Android有兩個限制,第一不能再主線程中直接請求網絡,第二不能在工作線程中直接更新UI,所以,如果我們在Android中直接使用okhttp,需要用到Handler來傳遞請求結果。而如果使用retrofit,則不需要我們去創建線程執行網絡請求,也不需要使用Handler把請求結果從工作線程傳遞到主線程。retrofit直接在主線程中發起異步請求,最後收到請求結果也是在主線程中,非常方便。
主要類和方法
Retrofit:retrofit框架的入口類,主要有兩個功能:
1、通過內部類Builder配置構建Retrofit實例。Builder主要配置選項:
1. client(OkHttpClient client) :設置一個配置好的OkHttpClient實例,不配置的話retrofit會默認new一個。
2. baseUrl(String baseUrl) :設置API地址。
3. addConverterFactory(Converter.Factory factory) :設置一個數據轉化工廠,比如把Json和實體類之間的轉化。
4. addCallAdapterFactory(CallAdapter.Factory factory):設置一個適配器工廠,方便和其他庫配合使用,如RxJava。
另外,如果我們沒有設置執行任務的線程池的話,Retrofit會根據不同的平臺,得到默認的線程池。
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
Android 中默認的線程池:
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
從上面代碼可以看到,先會創建一個在主線程中的Handler,然後默認線程池執行的任務都是在Android的主線程中執行的,這也是在Retrofit異步回調中我們能直接在裏面更新UI的原因。
另外,Retrofit根據不同使用平臺,會默認添加一個CallAdapterFactory
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
Android 中添加的是ExecutorCallAdapterFactory:
2、通過Retrofit的create方法,實現描述http請求的Java接口。
// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
我們在使用Retrofit時,首先要通過Retrofit實例來得到一個請求接口的實例(github),然後調用這個實例的一個方法(contributors)構造一個Call對象。這個過程主要是Retrofit的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);
}
});
}
當調用接口裏面方法的時候(github.contributors(“square”, “retrofit”) ),會執行InvocationHandler裏面的內容,通過反射,得到調用的method相關信息,然後構造ServiceMethod和OkHttpCall的實例,在Android中通過ExecutorCallAdapterFactory 把 OkHttpCall 進行轉換 ExecutorCallbackCall:
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
最後我們得到的Call對象實際上是ExecutorCallbackCall實例。得到Call實例之後,就可以通過call.enqueue進行網絡請求,我們看看ExecutorCallbackCall中的enqueue方法:
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("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);
}
});
}
});
}
在ExecutorCallbackCall中的enqueue裏面,又調用delegate.enqueue方法,這個delegate,其實是OkHttpCall對象,也就是調用OkHttpCall中的enqueue方法。
首先構造一個okhttp中的Request對象:
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;
}
可以看出,是通過ServiceMethod的toRequest方法得到的:
Request toRequest(Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
其中構造RequestBuilder的參數都是ServiceMethod 從Java接口中的註解解析出來的。
ServiceMethod: 從這個類的方法結構可以看出,這個類主要作用是把方法的註解解析成變量保存起來。