關(guān)于Retrofit的使用這里就不再贅述了,還不太了解Retrofit使用的同學(xué)
Retrofit簡(jiǎn)介
今天我們來(lái)聊一聊Retrofit的內(nèi)部實(shí)現(xiàn)眼滤,通過(guò)源碼來(lái)分析Retrofit的整個(gè)執(zhí)行順序爹耗。
在沒(méi)有框架的時(shí)候爹谭,做一次網(wǎng)絡(luò)請(qǐng)求大概會(huì)經(jīng)過(guò)五個(gè)步奏:
- 構(gòu)建request的參數(shù)
- 手動(dòng)開啟子線程做http請(qǐng)求
- 在子線程的run方法中具體請(qǐng)求
- 拿到返回的response數(shù)據(jù)后介时,回調(diào)給上一層
- 在主線程中更新UI
如果沒(méi)有網(wǎng)絡(luò)請(qǐng)求框架报咳,然后對(duì)多線程又不是太熟悉椎咧,就會(huì)出現(xiàn)很多問(wèn)題玖详。比如,請(qǐng)求是否異步勤讽,這里就會(huì)出現(xiàn)android中常見的錯(cuò)誤:Null pointer exception蟋座。
所以,在我們還沒(méi)有造輪子的能力的時(shí)候脚牍,多去看看優(yōu)秀框架的源碼是有好處的向臀,整個(gè)框架的搭建,運(yùn)用了哪些設(shè)計(jì)模式诸狭,容錯(cuò)處理等等券膀。君纫。
Retrofit 獲取實(shí)例
- 首先通過(guò)構(gòu)建者模式去獲得Retrofit實(shí)例
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiContancts.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
- 我們來(lái)看看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();
}
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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
不難看出build()方法中主要做了判空處理:
1.baseurl為空,拋出異常芹彬;
2.callFactory為空蓄髓,默認(rèn)使用OKhttp3的callFactory,這一點(diǎn)也可以看出Retrofit是基于okhttp3做的封裝舒帮。不會(huì)支持URLConnection和OkHttpClient了会喝。
3.callbackExecutor為空,會(huì)通過(guò)Platform這個(gè)類使用defaultCallbackExecutor
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);
}
}
}
跟蹤源碼會(huì)發(fā)現(xiàn)会前,最終會(huì)通過(guò)Handler去做操作好乐。
4.第一個(gè)List集合是存儲(chǔ)剛剛那個(gè)callbackExecutor匾竿,第二個(gè)List集合是存儲(chǔ)將Json轉(zhuǎn)換成實(shí)體類的一個(gè)工廠或者說(shuō)是適配器瓦宜。
5.最后返回一個(gè)Retrofit的實(shí)例。
Retrofit實(shí)例的create()方法
Call<CookListModel> cook = retrofit.create(ApiService.class).getCook(1,20);
通過(guò)調(diào)用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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
其實(shí)我看到這里也很懵逼岭妖,我們的Http請(qǐng)求方法临庇、參數(shù)是通過(guò)注解的方式創(chuàng)建的,它是怎么轉(zhuǎn)換成實(shí)體對(duì)象的昵慌?
不急假夺,我們一步一步的看下去
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
這里也用了構(gòu)建者模式,build()方法中調(diào)用parseMethodAnnotation()去解析注解
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);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} 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("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
那么斋攀,Retrofit到底是怎么把我們定義的接口轉(zhuǎn)換成http請(qǐng)求的呢已卷?
我們來(lái)看看ServiceMethod這個(gè)類。
Adapts an invocation of an interface method into an HTTP call.
ServiceMethod這個(gè)類相當(dāng)于一個(gè)適配器淳蔼,將interface轉(zhuǎn)換成http的請(qǐng)求侧蘸,再通過(guò)OkHttp去做網(wǎng)絡(luò)請(qǐng)求。
所以說(shuō)鹉梨,真正的關(guān)鍵代碼是:
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
Retrofit內(nèi)部大致的執(zhí)行流程就是這樣讳癌,如果想要更深入的去研究Retrofit的話,建議大家利用debug一步一步的跟蹤源碼分析存皂,這樣的話會(huì)更加容易理解一點(diǎn)晌坤。