在學習了Retrofit分析-漂亮的解耦套路(視頻版)後,本身又仔細的鑽研了一下Retrofit的源碼,也大體清楚了Retrofit進行網絡請求的步驟。好記性不如爛筆頭,以文章的形式將對於Retrofit的思考記錄下來,也加深理解。(若有錯誤,請不吝賜教)java
首先咱們聊一下對於一個優秀的libary,應該怎樣一步一步地分析它。在上面的視頻中,介紹了一個很好的方法。分爲三個階段:android
經過了解、深刻、思考,將整個框架一層一層地剖析出來,由淺入深,最後從全局再看這個框架,或許咱們會不自禁的讚歎代碼的美妙。git
詳細的瞭解Retrofit使用及API能夠到Retrofit的Github。github
首先,咱們須要建立一個請求接口,內部是一個請求方法,經過註解的方式定義請求類型及urljson
public interface IHttpRequestTest {
@GET("api/data/福利/{number}/{page}")
Call<BaseModel<ArrayList<Benefit>>> getBenefits(@Path("number") int number, @Path("page") int page);
}
複製代碼
而後咱們就能夠愉快地使用Retrofit。設計模式
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://gank.io/")
.addConverterFactory(GsonConverterFactory.create())
.build();
IHttpRequestTest iHttpRequestTest = retrofit.create(IHttpRequestTest.class);
Call<BaseModel<ArrayList<Benefit>>> call = iHttpRequestTest.getBenefits(40, 2);
call.enqueue(new Callback<BaseModel<ArrayList<Benefit>>>() {
@Override
public void onResponse(@NonNull Call<BaseModel<ArrayList<Benefit>>> call, @NonNull Response<BaseModel<ArrayList<Benefit>>> response) {
if(response.body() != null && response.body().results != null){
myAdapter.setData(response.body().results);
}
}
@Override
public void onFailure(@NonNull Call<BaseModel<ArrayList<Benefit>>> call, Throwable t) {
Toast.makeText(MainActivity.this, "請求失敗:" + t.getMessage(),Toast.LENGTH_SHORT).show();
}
});
複製代碼
接下來,咱們就能夠根據這個通常的http請求步驟,經過debug的形式弄清楚Retrofit的內部邏輯。api
首先第一步,就是生產Retrofit對象,並傳入基本的參數。緩存
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://gank.io/")
.addConverterFactory(GsonConverterFactory.create())
.build();
複製代碼
進入Retrofit類的源碼,能夠看到build方法網絡
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//若是callbackExcutor爲空,建立默認的callbackEcxutor
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//添加默認的callAdapterFactories
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.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,將使用默認的converterFactories
converterFactories.addAll(platform.defaultConverterFactories());
//返回Retrofit對象,包括在Builder中添加的自定義參數。
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
複製代碼
能夠看到,生成的retrofit對象有五個參數必需要存在。框架
baseUrl
就不用多說了,是必須的。callFactory
使用的是OkHttp3中的OkHttpClient
。callbackExcutor
與callAdapterFactory
中的callAdapter
都對應通常請求步驟中的Excutor
,只不過callbackExcutor
用於在請求內部回調中切換線程,回調的方法存在哪一個線程中取決於callbackExcutor
在哪一個線程。好比請求要在子線程中,回調的方法在主線程中。callAdapter
是真正的請求對象,callbackExcutor
至關於在callAdapter
中切換線程。converterFactory
是用來解析返回的json數據的。固然這些具體的解釋在下面的分析中都會看到。有源碼可看出,默認的callbackExcutor
、callAdapterFactory
、converterFactory
添加都與platform
對象有關。這是一個Platform
類,進入研究一下。
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();
}
@Nullable Executor defaultCallbackExecutor() {return null;}
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {...}
List<? extends Converter.Factory> defaultConverterFactories() {...}
@IgnoreJRERequirement // Only classloaded and used on Java 8.
static class Java8 extends Platform {...}
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@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);
}
@Override List<? extends Converter.Factory> defaultConverterFactories() {
return Build.VERSION.SDK_INT >= 24
? singletonList(OptionalConverterFactory.INSTANCE)
: Collections.<Converter.Factory>emptyList();
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
}
複製代碼
內容有點多,這裏我只提取了對如今有用的。總體來看,Platform
內部有兩個子類繼承了該類Android與Java8
。還有一個get方法,獲取Platform靜態實例,靜態實例調用findPlatform()方法。這個方法是根據程序所執行的環境決定是返回一個Android
實例仍是Java8
實例或者Platform
實例。這裏咱們的環境是Android
,因此具體看Android
類中的方法。
MainThreadExecutor
類實例。此類在Android類內部,能夠清晰的看出其中的handler靜態變量是用的主線程的looper。也就是說,默認的callbackExcutor
是運行在主線程的。callbackExcutor
。方法內部建立了ExecutorCallAdapterFactory
類實例,並返回該實例的List。OptionalConverterFactory
實例,此類中的轉換converter()
方法只檢查了參數是否爲空就將其返回了,說明默認的回調數據是不進行任何轉換的。至此,三個默認參數已肯定。
IHttpRequestTest iHttpRequestTest = retrofit.create(IHttpRequestTest.class);
這是接下來的執行步驟,自定義接口對象由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();
private final Object[] emptyArgs = new Object[0];
@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);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
複製代碼
該方法返回的是經過反射得到自定義接口的代理類,並在類中重寫了invoke方法。這代表當該類中的方法被執行時,就會攔截此方法。
Call<BaseModel<ArrayList<Benefit>>> call = iHttpRequestTest.getBenefits(40, 2);
由上一步驟可知,當執行代理類中的方法時,會被攔截。並最終執行loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
方法並返回。先看一下loadServiceMethod(method)
方法。
ServiceMethod<?> loadServiceMethod(Method method) {
//serviceMethodCache,若是執行過此方法,就會有緩存存在這裏,直接取出便可
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(this, method)
方法裏。
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);
}
複製代碼
這是一個抽象類,第一句RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
,是解析方法構建request參數的。RequestFactory類中內容比較多,簡單講一下就是經過得到方法註解、返回類型、方法參數,分別進行解析。
最後它又跑到HttpServiceMethod
類中了。此類繼承了ServiceMethod
類。
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);
}
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method) {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
}
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter( Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
return retrofit.responseBodyConverter(responseType, annotations);
}
複製代碼
簡化了異常檢測類代碼,能夠看到最後返回的是HttpServiceMethod
類的實例對象,並將retrofit中的一些默認參數傳了進去。
解析完了loadServiceMethod(method)
,接下來就是執行invoke方法了。因爲loadServiceMethod(method)
返回的是HttpServiceMethod
類的實例對象,因此執行的就是HttpServiceMethod
類中的invoke方法。
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
複製代碼
此方法很簡單,調用了callAdapter中的adapt方法,參數是一個OkHttpCall,字面意思就是將OkHttpCall
適配爲其餘類。那麼這個類是什麼什麼呢。應該是咱們須要返回的Call<BaseModel<ArrayList<Benefit>>>
類。那麼怎麼適配的呢。上面咱們已經說到,retrofi中的默認參數callAdapterFactories
是ExecutorCallAdapterFactory
類,而callAdapterFactories
中的callAdapter
是經過callAdapterFactories.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);
}
};
}
複製代碼
返回的CallAdapter
對象就是咱們須要的。其中重寫了adapt方法,也是咱們要找的。它又返回了ExecutorCallbackCall
對象,第一個參數就是默認運行在主線程中的callbackExecutor
,第二個參數則是調用時傳進來的OkHttpCall
對象。因此說咱們須要返回的Call<BaseModel<ArrayList<Benefit>>>
對象就是ExecutorCallbackCall
對象。
call.enqueue(new Callback<BaseModel<ArrayList<Benefit>>>() {...});
,終於到最後一步了,拿着上一步返回的Call<BaseModel<ArrayList<Benefit>>>
對象進行異步請求。調用了enqueue方法,也就是ExecutorCallbackCall
中的enqueue方法。
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);
}
});
}
});
}
複製代碼
構造方法給了出來,變量名有些轉換。callbackExecutor
依然是在主線程中的那個callbackExecutor
,delegate
是上一步傳進來的OkHttpCall
對象。而enqueue的參數callback則是咱們本身傳入的callback。
方法中首先是delegate
也就是OkHttp3進行的異步請求,在回調的函數中,經過callbackExecutor
使線程切換爲主線程,再調用咱們本身的callback中對應的函數,使咱們能夠再回調中進行操做,而且是在主線程中。
OkHttpCall
這個類就不在多講了,主要做用是retrofit經過OkHttp3進行請求的一個轉換。
第一次分析源碼,雖然有視頻的幫助,但許多類之間跳來跳去的讓人眼花繚亂,很艱難地順了下來。有了這樣一個大概的瞭解,接下來就要分析其設計模式,欣賞其漂亮的解耦套路。固然,若是你已經有了上面的瞭解,接下來看Retrofit分析-經典設計模式案例就會簡單明瞭。