Retrofit黍聂,OkHttp,Okio Square 安卓平臺(tái)網(wǎng)絡(luò)層三板斧源碼學(xué)習(xí)
基于 retrofit 2.4.0-SNAPSHOT 版本 retrofit github 地址
Retrofit 是 Square 安卓平臺(tái)網(wǎng)絡(luò)層三板斧最后一個(gè)項(xiàng)目范咨,Retrofit 依賴(lài) OkHttp 稠屠。Retrofit 讓 http 網(wǎng)絡(luò)請(qǐng)求更加清晰。
使用方式
-
聲明一個(gè)接口质礼,并用接口描述 request
public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); }
方法上面的注釋表示 request 的接口名 ,方法的返回類(lèi)型就是 http 請(qǐng)求的返回值市栗,方法的參數(shù)就是 http 的請(qǐng)求參數(shù)缀拭。
-
創(chuàng)建一個(gè) Retrofit 客戶(hù)端
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service = retrofit.create(GitHubService.class);
Retrofit 創(chuàng)建的時(shí)候指定了 request 的接口地址,然后調(diào)用 retrofit.create 方法創(chuàng)建一個(gè) GitHubService 實(shí)例填帽。
-
發(fā)起網(wǎng)絡(luò)請(qǐng)求
Call<List<Repo>> repos = service.listRepos("octocat"); repos.execute().body()
Retrofit 創(chuàng)建 Service 實(shí)例
上面的例子可以看到蛛淋,retrofit.create() 方法會(huì)創(chuàng)建一個(gè) GitHubService 實(shí)例,但是 GitHubService 本身是一個(gè)接口篡腌。為了了解 retrofit.create() 方法褐荷,我們先看下 Retrofit 的創(chuàng)建過(guò)程。
創(chuàng)建 Retrofit 對(duì)象嘹悼。
Retrofit 和 OkHttp 一樣都是使用構(gòu)建者模式創(chuàng)建對(duì)象叛甫。先看下 Retrofit.Builder 的 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);
}
創(chuàng)建 Retrofit 的時(shí)候需要傳遞一下幾個(gè)參數(shù)
1. callFactory 用來(lái)創(chuàng)建一個(gè)實(shí)現(xiàn)了 okhttp3.Call.Factory 的對(duì)象,如果沒(méi)有設(shè)置其监,默認(rèn)為 OkHttpClient萌腿。
2. baseUrl 網(wǎng)絡(luò)接口的地址。
3. converterFactories 用來(lái)把服務(wù)器返回的數(shù)據(jù)轉(zhuǎn)換為對(duì)象抖苦。
4. adapterFactories 用來(lái)發(fā)起網(wǎng)絡(luò)請(qǐng)求毁菱。
5. callbackExecutor 是一個(gè)調(diào)度器,用來(lái)接收返回的數(shù)據(jù)锌历,在 Android 上默認(rèn)是封裝了 handler 的 MainThreadExecutor
6. validateEagerly 是一個(gè)開(kāi)關(guān)鼎俘,如果為 true 會(huì)緩存創(chuàng)建的 ServiceMethod 。
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, @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);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
這里用到了一個(gè)公共技術(shù)點(diǎn)之 Java 動(dòng)態(tài)代理辩涝,create 方法傳入一個(gè) Class ,這個(gè) Class 對(duì)象就是上文的 GitHubService 的 Class 勘天。
GitHubService 的方法是由 InvocationHandler 代理實(shí)現(xiàn)的怔揩,重點(diǎn)看三行代碼
……
ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
第一行 loadServiceMethod(method)
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;
}
這里創(chuàng)建了一個(gè) ServiceMethod 對(duì)象。
第二行 new OkHttpCall<>(serviceMethod, args)
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
創(chuàng)建了一個(gè) OkHttpCall 脯丝,serviceMethod 和 args 是 OkHttpCall 的成員函數(shù)商膊。
所以,
第三行 serviceMethod.callAdapter.adapt(okHttpCall)
這里需要明白 serviceMethod.callAdapter 是怎么來(lái)的
1. 在 ServiceMethod.Builder.build() 中調(diào)用 createCallAdapter()
2. 在 createCallAdapter() 中會(huì)找到
(CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations)
3. 在 callAdapter() 中調(diào)用 nextCallAdapter
4. nextCallAdapter 會(huì)遍歷 adapterFactories 返回一個(gè) CallAdapter宠进。
這里再回頭看下 adapterFactories Retrofit.Builder.build() 方法中
List<CallAdapter.Factory> adapterFactories =
new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
而在 Retrofit.nextCallAdapter() 中
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
如果沒(méi)有設(shè)置 AdapterFactory 將會(huì)使用一個(gè)默認(rèn)的 AdapterFactory
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
所以如果我們?cè)O(shè)置了一個(gè) RxJavaCallAdapterFactory晕拆,就會(huì)返回 RxJavaCallAdapterFactory。
發(fā)起網(wǎng)絡(luò)請(qǐng)求
通過(guò) retrofit.create() 我們可以知道材蹬,retrofit.create() 返回的是一個(gè)代理對(duì)象InvocationHandler 实幕,那么在執(zhí)行
Call<List<Repo>> repos = service.listRepos("octocat");
方法時(shí),調(diào)用的實(shí)際上是 callAdapter.adapt(okHttpCall)堤器,以 DefaultCallAdapterFactory 為例
@Override
public 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 call;
}
};
}
結(jié)合 retrofit.create() 方法可以得知這里返回的是一個(gè) OkHttpCall 對(duì)象昆庇。
接下來(lái)使用 OkHttpCall.execute() 或者異步執(zhí)行 enqueue(Callback<T> callback)
這兩種方式都會(huì)調(diào)用 createRawCall() 創(chuàng)建一個(gè) okhttp3.Call
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.callFactory 就是 retrofit.create() 中創(chuàng)建的 OkHttpClient()
后面的內(nèi)容都是由 Okhttp 模塊接管,進(jìn)行網(wǎng)絡(luò)請(qǐng)求闸溃,參考okHttp 框架源碼學(xué)習(xí)
然后調(diào)用 parseResponse(call.execute())
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
……
省略一些 http 返回值處理邏輯
……
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} ……
}
okHttp 請(qǐng)求網(wǎng)絡(luò)的返回?cái)?shù)據(jù)整吆,會(huì)交給 serviceMethod.toResponse
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
在 ServiceMethod.Builder.build() 方法中可以找到 responseConverter 是通過(guò) createResponseConverter() 方法的返回對(duì)象。
createResponseConverter() 只是報(bào)包裹了 retrofit.responseBodyConverter(responseType, annotations) 方法辉川。
retrofit.responseBodyConverter() 繼續(xù)跟蹤下去會(huì)得知表蝙,返回的是 converterFactories 數(shù)組的第 0 個(gè)對(duì)象,也就是內(nèi)置的 BuiltInConverters.responseBodyConverter() 方法返回的 BufferingResponseBodyConverter
static final class BufferingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();
@Override
public ResponseBody convert(ResponseBody value) throws IOException {
try {
// Buffer the entire body to avoid future I/O.
return Utils.buffer(value);
} finally {
value.close();
}
}
}
再看一下 Utils.buffer(value)
static ResponseBody buffer(final ResponseBody body) throws IOException {
Buffer buffer = new Buffer();
body.source().readAll(buffer);
return ResponseBody.create(body.contentType(), body.contentLength(), buffer);
}
最終會(huì)返回一個(gè)重新封裝的 Okhttp 框架的 ResponseBody 對(duì)象乓旗。
參考資料
Android:手把手帶你深入剖析 Retrofit 2.0 源碼