首先介紹下Retrofit基本用法晚缩,先創(chuàng)建接口浅役,注解申明、請求方式Post/Get等
public interface Service {
@POST("list")
Call<User> loadRepo();
}
基本使用如下
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.reibang.com/u/c030e2bc8731")
.build();
Service service = retrofit.create(Service.class);
Call<User> userCall = service.loadRepo();
userCall.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
}
@Override
public void onFailure(Call<User> call, Throwable t) {
}
});
上面是簡單的網(wǎng)絡(luò)請求流程瞻凤,那么我們來分析具體是怎么實(shí)現(xiàn)的憨攒,直接看源碼
Retrofit.Builder()方法
首先Retrofit.Builder()中Platform.get()最后調(diào)用findPlatform()得到平臺(tái)信息,可以看到支持Android阀参、Java8平臺(tái),其中還對Converter.Factory 設(shè)置默認(rèn)值肝集。
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();
}
Retrofit.Builder().builder()方法
public Retrofit build() {
//baseUrl必須不為空
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//OkHttpClient對象
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//將回調(diào)傳遞,此時(shí)platform為Android 平臺(tái)蛛壳,在Retrofit.Builder()中初始化
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);
//將callbackExecutor轉(zhuǎn)化成ExecutorCallAdapterFactory并添加到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);
}
1)以上可見baseUrl必須傳杏瞻,null則拋出異常。
2)若未傳入OkHttpClient則默認(rèn)創(chuàng)建一個(gè)衙荐,此處callFactory即OkHttpClient對象捞挥,OkHttpClient實(shí)現(xiàn)了okhttp3.Call.Factory接口。
3)callbackExecutor赫模,是用來將回調(diào)切換到主線程中去树肃,此處利用platform對象,對平臺(tái)進(jìn)行判斷瀑罗,判斷主要是利用Class.forName("")進(jìn)行查找胸嘴,如果是Android平臺(tái),會(huì)自定義一個(gè)Executor對象MainThreadExecutor斩祭,并且利用Looper.getMainLooper()實(shí)例化一個(gè)handler對象劣像,在Executor內(nèi)部通過handler.post(runnable),代碼如下:
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);
}
}
}
4)adapterFactories摧玫,這個(gè)對象主要用于對Call進(jìn)行轉(zhuǎn)化耳奕。創(chuàng)建callbackExecutor即MainThreadExecutor對象,MainThreadExecutor
5)converterFactories 轉(zhuǎn)換器工廠诬像,該對象用于轉(zhuǎn)化數(shù)據(jù)屋群,例如將返回的responseBody轉(zhuǎn)化為對象等;當(dāng)然不僅僅是針對返回的數(shù)據(jù)坏挠,還能用于一般備注解的參數(shù)的轉(zhuǎn)化例如@Body標(biāo)識(shí)的對象做一些操作等芍躏。
retrofit.create(Service.class)
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
......
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
......
@Override public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
......
ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
分三個(gè)步驟,第一根據(jù)我們的method將其包裝成ServiceMethod降狠,第二通過ServiceMethod和方法的參數(shù)構(gòu)造retrofit2.OkHttpCall對象对竣,第三通過serviceMethod.callAdapter.adapt()方法庇楞,將OkHttpCall進(jìn)行代理包裝;
1>將method包裝成ServiceMethod
下面看Retrofit的loadServiceMethod()方法:
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;
}
可見將method緩存在Map中否纬,所以Retrofit帶有緩存吕晌,第二次網(wǎng)絡(luò)請求相同方法時(shí),會(huì)避免創(chuàng)建實(shí)例化和解析注解临燃,減少響應(yīng)時(shí)間睛驳。
ServiceMethod.build():
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
1)以上代碼中callAdapter為在Retrofit.Builder.build中platform.defaultCallAdapterFactory(callbackExecutor)創(chuàng)建,在createCallAdapter()中獲取方法的注解和Bean的數(shù)據(jù)類型谬俄,最后調(diào)用ExecutorCallAdapterFactory.get()取出柏靶,callAdapter的作用是將回調(diào)傳遞到UI線程。
2)callAdapter.responseType()返回的是我們方法的實(shí)際類型溃论,例如:Call<User>,則返回User類型屎蜓,然后對該類型進(jìn)行判斷。
3)createResponseConverter()得到responseConverter轉(zhuǎn)換器對象钥勋,它的作用是尋找合適的數(shù)據(jù)類型轉(zhuǎn)換器炬转。在構(gòu)建retrofit時(shí),addConverterFactory添加的ConverterFactory對象來尋找一個(gè)合適的返回,尋找的依據(jù)主要看該converter能否處理你編寫方法的返回值類型算灸,默認(rèn)實(shí)現(xiàn)為BuiltInConverters扼劈,僅僅支持返回值的實(shí)際類型為ResponseBody和Void,也就說明了默認(rèn)情況下菲驴,是不支持Call<User>這類類型的荐吵。
2>通過ServiceMethod和方法的參數(shù)構(gòu)造retrofit2.OkHttpCall對象
OkHttpCall構(gòu)造方法中對方法參數(shù)進(jìn)行賦值
OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
3>通過serviceMethod.callAdapter.adapt()方法,將OkHttpCall進(jìn)行代理包裝
serviceMethod.callAdapter.adapt(okHttpCall)
上面說了callAdapter通過CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
獲得赊瞬,而adapterFactories.get(i)得到的call對象是ExecutorCallAdapterFactory先煎。當(dāng)通過retrofit的create()方法再獲得call對象,調(diào)用call.enque()去訪問網(wǎng)絡(luò)時(shí)巧涧,方法中有回掉函數(shù)薯蝎,回掉函數(shù)里重寫兩個(gè)方法,一個(gè)成功谤绳,一個(gè)失斦季狻;這個(gè)call對象其實(shí)就是ExcutorCallAdapterFactory缩筛。callAdapter是ExecutorCallAdapterFactory.get()方法得到的消略。
看return new CallAdapter中的adapt(Call call)我們可以知道,在我們得到接口的代理實(shí)例之后瞎抛,通過代理接口調(diào)用里面的方法疑俭,就會(huì)觸發(fā)InvocationHandler對象中的invoke方法,從而完成上面的三個(gè)步驟并且返回一個(gè)Call對象婿失,通過Call對象就可以去完成我們的請求了钞艇。
從下面代碼可以看出adapt返回的是ExecutorCallbackCall對象。
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@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
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
再看下面代碼可以看出ExecutorCallbackCall是對 Call<T> delegate 的封裝豪硅,delegate 就是OkHttpCall對象哩照,enqueue即是調(diào)用OkHttpCall的方法enqueue而已。
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@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);
}
});
}
});
}
再來看OkHttpCall的方法enqueue()方法懒浮,也是調(diào)用okhttp3.Call的enqueue()方法飘弧,下面代碼中可以看到 createRawCall()中對okhttp3.Call初始化;另通過parseResponse()構(gòu)建Response對象砚著。
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
//okhttp3.Call call初始化
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
//構(gòu)造Response對象
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
createRawCall() 中通過serviceMethod.toRequest()構(gòu)造Requset對象次伶,再通過request構(gòu)造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;
}
parseResponse()是中邏輯為通過serviceMethod對ResponseBody進(jìn)行轉(zhuǎn)化稽穆,然后返回冠王,轉(zhuǎn)化實(shí)際上就是通過responseConverter的convert方法。
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
......
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
}
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
好了關(guān)于Retrofit2.0的源碼分析就到這里舌镶,下面總結(jié)一下:
1)首先構(gòu)造retrofit柱彻,核心的參數(shù)是baseurl,callFactory(默認(rèn)okhttpclient)、converterFactories餐胀、adapterFactories哟楷、excallbackExecutor。
2)其次通過create得到接口的實(shí)現(xiàn)類否灾,利用Proxy類完成動(dòng)態(tài)代理的相關(guān)代理卖擅。在我們得到接口的代理實(shí)例之后,通過代理接口調(diào)用里面的方法墨技,就會(huì)觸發(fā)InvocationHandler對象中的invoke方法惩阶,從而完成上面的三個(gè)步驟并且返回一個(gè)Call對象。
3)拿到Call執(zhí)行enqueue或者execute方法健提。
由此Retrofit完成整個(gè)請求回調(diào)流程琳猫。