不忘初心 砥礪前行, Tomorrow Is Another Day !java
本文概要:設計模式
在分析Retrofit以前,咱們須要對基本的網絡以及網絡框架有個綜合的對比認識.api
okHttp、urlConnection、httpClient、volley、retrofit之間的關係緩存
Retrofit的使用比較簡單,基本是就是經過三類註解方法註解,參數註解. 這裏就再也不講述了,找了一篇我的感受比較全面的文章你真的會用Retrofit2嗎?Retrofit2徹底教程進行參考學習.咱們重點進行原理分析.bash
源碼版本2.5.0
Retrofit是經過動態代理的方式建立各類網絡接口的代理.網絡
關於動態代理,筆者另起了篇講述.設計模式之代理模式若有興趣的能夠看一下.最後咱們迴歸正題.框架
使用過程通常都是經過建造者的build方法來構建Retorfit對象.咱們就從Retorfit對象的建立開始,異步
使用示例-1ide
mRetrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.callFactory(okHttpClient)
.build();
複製代碼
直接看build方法的對應源碼oop
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 1.初始化callFactory,若是未設置則默認設置一個OkHttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 2.初始化回調執行器,用於回調到UI線程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 3.初始化適配器工廠集合,添加一個默認適配器工廠(ExecutorCallAdapterFactory)
//用於適配返回類型,如默認支持的Call<T>
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 4.初始化轉換器集合
//用於網絡響應的解析
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
//...省略部分代碼
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
複製代碼
在build方法裏,初始化時會經過platform對象添加一些默認的適配器,轉換器,以及回調執行器.咱們看具體的添加操做.
對應源碼
static class Android extends Platform {
@IgnoreJRERequirement // Guarded by API check.
@Override boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}
//添加默認回調執行器
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//添加默認的適配器工廠(ExecutorCallAdapterFactory)
@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 int defaultCallAdapterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
}
//添加默認的轉換器工廠
@Override List<? extends Converter.Factory> defaultConverterFactories() {
return Build.VERSION.SDK_INT >= 24
? singletonList(OptionalConverterFactory.INSTANCE)
: Collections.<Converter.Factory>emptyList();
}
@Override int defaultConverterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
}
static class MainThreadExecutor implements Executor {
//綁定主線程的looper
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
//回調到主線程執行
handler.post(r);
}
}
}
複製代碼
至此Retorfit對象建立過程就分析完了,作一個小結.
對於Retorfit的建立,進行一系列的初始化操做.
- 初始化callFactory
- 初始化"三器"
- 回調執行器,用於回調到UI線程
- 適配器工廠,用於適配返回的類型
- 轉換器工廠,用於解析網絡響應
Call的建立過程實質是網絡接口的實現過程
Rerofit對象建立完成後,調用create方法時來實現咱們定義的網絡接口ApiService,採用的就是動態代理.
使用示例-2
定義的網絡接口類
public interface ApiService{
@GET
Observable<IDocViewBean> oaFileUpload(@Url String url,
@Query("token") String token,
@Query("mode") String mode,
@Query("url") String urlFile);
}
ApiService apiService = retrofit.create(ApiService.class);
複製代碼
對應源碼
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
/*
* 返回了網絡接口的代理對象
*/
//當咱們調用代理對象的接口方法時,會觸發InvocationHandler的invoke方法.
//如調用apiService.oaFileUpload(...)時,會完成oaFileUpload的實現,並返回一個Call<T>
//如調用apiService.oaFileUpload(...)時,會完成oaFileUpload的實現,並返回一個Call<T>
//如調用apiService.oaFileUpload(...)時,會完成oaFileUpload的實現,並返回一個Call<T>
//重要話說三遍,這一句理解了後面就容易了.
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);
}
//加載網絡接口的方法,如加載oaFileUpload方法並調用.
/**
* 第一大步:先分析loadServiceMethod(method)獲取到網絡接口方法對象(ServiceMethod對象)
* 第二大步:調用ServiceMethod的invoke.
*/
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
複製代碼
接着咱們看loadServiceMethod的具體實現
對應源碼
ServiceMethod<?> loadServiceMethod(Method method) {
//先從緩存中獲取.
ServiceMethod<?> result = serviceMethodCache.get(method);
//有緩存,直接返回.
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//無緩存,對網絡接口的方法進行解析,封裝成ServiceMethod並添加進緩存.
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
複製代碼
對網絡接口的方法進行解析調用的了ServiceMethod.parseAnnotations,實際調用的是它的子類HttpServiceMethod.parseAnnotations方法.這裏咱們直接看子類的方法.
對應源碼
//HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
//建立CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
//建立轉換器
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();
try {
//noinspection unchecked
//裏面經過retrofit對象的callAdapter方法獲取CallAdapter對象
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);
}
}
複製代碼
createCallAdapter方法調用了retrofit對象的callAdapter方法獲取CallAdapter對象.接着看retrofit的CallAdapter方法.
對應源碼
//retrofit.java
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;
//先遍歷callAdapterFactories集合
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
//再經過網絡接口的返回類型(returnType)來獲取適配器工廠(CallAdapter.Factory),最終獲取到CallAdapter對象.
//再經過網絡接口的返回類型(returnType)來獲取適配器工廠(CallAdapter.Factory),最終獲取到CallAdapter對象.
//再經過網絡接口的返回類型(returnType)來獲取適配器工廠(CallAdapter.Factory),最終獲取到CallAdapter對象.
//重要的話說三遍.
//因爲以前在Retrofit對象建立階段時,有默認設置CallAdapter.Factory爲ExecutorCallAdapterFactory,那麼遍歷時就會獲取到它.
//最後一塊兒看下ExecutorCallAdapterFactory的get方法.
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
複製代碼
//ExecutorCallAdapterFactory.java
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
//檢測返回類型是否是CALL
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
//返回一個CallAdapter對象,終於找到源頭了,不容易啊.至此第一大步到此爲止
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
//...省略部分代碼
};
}
複製代碼
調用ServiceMethod實際調用了HttpServiceMethod的invoke方法,咱們直接看這個方法.
//HttpServiceMethod.java
@Override ReturnT invoke(Object[] args) {
/*由於以前第一大步咱們已經清楚,默認狀況下callAdapter是ExecutorCallAdapterFactory適配器工廠下返回的,
那麼繼續往下看適配器工廠找adapt
*/
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
//ExecutorCallAdapterFactory.java
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
//...省略部分代碼
@Override
public Call<Object> adapt(Call<Object> call) {
//返回的Call實際上就是ExecutorCallbackCall
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
複製代碼
Call的建立過程相對來講比較複雜,須要反覆多瀏覽幾遍,關鍵在於冷靜下來根據線索去尋找.最後對Call的建立過程作一個總結.
- 當調用代理對象的網絡接口方法時,會觸發InvocationHandler的invoke方法,最終返回一個Call.
- 在invoke方法裏面主要包含兩大步驟.
- 第一大步,獲取到網絡接口方法對象(loadServiceMethod)
- 檢查是否有緩存,有直接返回,無,從新解析生成新的對象後,緩存再返回
- 解析時獲取適配器(CallAdapter),遍歷適配器工廠集合,經過網絡接口的返回類型(returnType)來獲取對應適配器工廠,最終得到適配器(CallAdapter).
- 第二大步,調用ServiceMethod的invoke發送請求.
- 一樣利用獲取到的CallAdapter調用adapt方法,返回一個Call對象.最後發送請求.
最後咱們看ExecutorCallbackCall是如何發請求和回調的.
對應源碼
static final class ExecutorCallbackCall<T> implements Call<T> {
//初始化時設置的線程回調執行器
final Executor callbackExecutor;
//爲OkHttpCall
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>() {//使用okhttpClient進行異步請求
//網絡回調成功
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
//主線程回調失敗
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);
}
});
}
});
}
//...省略部分代碼
}
複製代碼
最後老規矩,對網絡請求的發送過程作一個小結.
經過enqueue方法,利用Okhttp發送網絡請求,網絡響應成功或失敗經過回調執行器(MainThreadExecutor)分發到主線程執行.
因爲本人技術有限,若有錯誤的地方,麻煩你們給我提出來,本人不勝感激,你們一塊兒學習進步.