前言
????????Retrofit是Square公司開(kāi)源的一個(gè)針對(duì)OkHttp網(wǎng)絡(luò)請(qǐng)求接口進(jìn)行二次封裝的框架镰官,其網(wǎng)絡(luò)請(qǐng)求的實(shí)質(zhì)工作仍是由OkHttp來(lái)完成纵竖,主要工作是將網(wǎng)絡(luò)請(qǐng)求通過(guò)一系列注解的形式進(jìn)行拆解,并在最終執(zhí)行網(wǎng)絡(luò)請(qǐng)求前来累,將注解解析生成OkHttp請(qǐng)求所需的Okhttp3.Call泉褐。通過(guò)分析Retrofit源碼规哪,來(lái)達(dá)到深入理解Retrofit的工作流程與原理蛤袒,以及學(xué)習(xí)一些值得借鑒的設(shè)計(jì)模式和啟發(fā)一些解決問(wèn)題的思路熄云。
????????對(duì)于源碼中各種參數(shù)類型的相關(guān)知識(shí),如有不理解的地方妙真,可以參考賈博巖的兩篇文章:我眼中的Java-Type體系缴允。
http://www.reibang.com/p/7649f86614d3
http://www.reibang.com/p/e8eeff12c306
基本使用
第一步:集成
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
第二步:創(chuàng)建接口
public interface JianShuApi {
@GET("user/{userName}/info")
Observable<ResponseBody> getPersonalInfo(@Path("userName") String userName);
}
第三步:配置Retrofit并實(shí)例化
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.reibang.com")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
第四步:獲取接口對(duì)象
JianShuApi api = retrofit.create(JianShuApi.class);
第五步:執(zhí)行請(qǐng)求
Call<ResponseBody> call = api.getPersonalInfo("zhangSanLisi");
//異步請(qǐng)求
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//成功回調(diào)
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//失敗回調(diào)
}
});
//同步請(qǐng)求
try {
Response<ResponseBody> response = call.execute();
} catch (IOException e) {
e.printStackTrace();
}
源碼分析
下面我們按照使用流程來(lái)分析:
1、自定義接口類
里面的請(qǐng)求方法珍德,主要通過(guò)注解的方式來(lái)實(shí)現(xiàn)各種參數(shù)的靈活配置练般。如常用的請(qǐng)求方式@POST @GET,添加請(qǐng)求參數(shù)的@Query @QueryMap菱阵,大文件下載@Streaming踢俄,多文件提交@Multipart,請(qǐng)求頭內(nèi)容@Header @Headers...晴及,具體注解使用請(qǐng)參考retrofit2.http里面的內(nèi)容,每個(gè)注解都有相關(guān)的注釋嫡锌。
2虑稼、Retrofit.Builder
通過(guò)Retrofit.Builder構(gòu)造者模式來(lái)實(shí)例化Retrofit對(duì)象,主要可配置的內(nèi)容如下:
public static final class Builder {
// 具體使用平臺(tái)势木,Platform.get()方法來(lái)獲取蛛倦,這里只分析Android
private final Platform platform;
// 指定用來(lái)構(gòu)建Call實(shí)例的Call.Factory類
private @Nullable okhttp3.Call.Factory callFactory;
// 請(qǐng)求的baseUrl,注釋建議我們使用相對(duì)路徑的方式來(lái)配置
// Base URL: http://example.com/api/
// Endpoint: foo/bar/
// Result: http://example.com/api/foo/bar/
private HttpUrl baseUrl;
// 用于對(duì)象序列化(serialization)和反序列化(deserialization)啦桌,常用GsonConverterFactory
private final List<Converter.Factory> converterFactories = new ArrayList<>();
// 請(qǐng)求返回類型(除了Call之外)溯壶,若Retrofit結(jié)合RxJava一起使用,那么就可以添加RxJava2CallAdapterFactory
// 來(lái)返回Observable類型甫男,無(wú)縫對(duì)接RxJava
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
// 異步回調(diào)執(zhí)行者
private @Nullable Executor callbackExecutor;
// 是否提前校驗(yàn)注解方法
private boolean validateEagerly;
......
public Retrofit build() {
// 必須指定baseUrl且改,否則異常
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//默認(rèn)OkHttpClient來(lái)創(chuàng)建請(qǐng)求Call
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// Android平臺(tái)默認(rèn)回調(diào)在主線程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 默認(rèn)添加一個(gè)CallAdapter和Converter
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size());
// 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);
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
}
3、Retrofit.create()
public final class Retrofit {
......
public <T> T create(final Class<T> service) {
// 校驗(yàn)class必須是接口板驳,并且不能繼承其他接口
Utils.validateServiceInterface(service);
// 是否提前校驗(yàn)方法又跛,提前創(chuàng)建ServiceMethod,如果自定義的接口方法存在不合規(guī)范則拋出異常
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 返回一個(gè)代理對(duì)象若治,當(dāng)調(diào)用api方法的時(shí)候慨蓝,代理對(duì)象執(zhí)行
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和請(qǐng)求OkHttpCall
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 執(zhí)行adapt方法,返回指定的數(shù)據(jù)類型礼烈,具體內(nèi)容會(huì)在后面CallAdapter類中說(shuō)明
return serviceMethod.adapt(okHttpCall);
}
});
}
......
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
// 同步鎖
synchronized (serviceMethodCache) {
// 通過(guò)method對(duì)象弧满,獲取對(duì)應(yīng)緩存的ServiceMethod
result = serviceMethodCache.get(method);
if (result == null) {
// 創(chuàng)建ServiceMethod并存入緩存
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
......
}
到這里我們就拿到了接口代理對(duì)象對(duì)象,當(dāng)調(diào)用接口具體方法api.getPersonalInfo("zhangSanLisi");
的時(shí)候就會(huì)執(zhí)行invoke方法此熬,獲取創(chuàng)建的ServiceMethod對(duì)象庭呜,執(zhí)行serviceMethod.adapt(okHttpCall)
方法,這里我們指定了請(qǐng)求適配器為RxJava2CallAdapter摹迷,則返回Observable疟赊。具體參見(jiàn)下面RxJava2CallAdapter的adapt方法
4、ServiceMethod
這是Retrofit框架核心類峡碉。ServiceMethod類功能是將自定義的接口方法解析適配成Http調(diào)用的Call近哟,也就是生成Http請(qǐng)求。該類也是通過(guò)構(gòu)造者模式實(shí)例化:new ServiceMethod.Builder<>(this, method).build()鲫寄。
final class ServiceMethod<R, T> {
......
// 這個(gè)方法會(huì)在創(chuàng)建真正OkHttp請(qǐng)求時(shí)調(diào)用吉执,即OkHttpCall類中createRawCall()方法
// 參見(jiàn)下面OkHttpCall分析里enqueue方法
okhttp3.Call toCall(@Nullable Object... args) throws IOException {
// 通過(guò)構(gòu)造者模式RequestBuilder來(lái)創(chuàng)建請(qǐng)求Request
// 里面有使用到ServiceMethod生成的ParameterHandler對(duì)象,主要是解析不同的請(qǐng)求參數(shù)地来,大家可自行查看源碼分析
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
// 最終回通過(guò)Retrofit里面指定的callFactory執(zhí)行戳玫,這里不指定時(shí),默認(rèn)是OkHttpClient未斑,這里不做進(jìn)一步分析咕宿,具體可參考OkHttp源碼。
return callFactory.newCall(requestBuilder.build());
}
......
static final class Builder<T, R> {
......
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
// 獲取方法注解蜡秽, 如@POST府阀、@Headers
this.methodAnnotations = method.getAnnotations();
// 獲取方法參數(shù)類型,如String
this.parameterTypes = method.getGenericParameterTypes();
// 獲取方法參數(shù)注解芽突,如@Query
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build () {
/*
* 一系列判斷之后調(diào)用的是 (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
* 遍歷Retrofit配置時(shí)設(shè)置的callAdapterFactories试浙,如果設(shè)置的是RxJava2CallAdapterFactory最終調(diào)用其get方法;
* 經(jīng)過(guò)一系列的返回類型判斷寞蚌,最終返回CallAdapter田巴,這里也就是RxJava2CallAdapter
*/
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?");
}
/*
* 獲取轉(zhuǎn)換器,也就是序列化和反序列化方式挟秤,retrofit.responseBodyConverter(responseType, annotations);
* 遍歷Retrofit配置時(shí)設(shè)置的converterFactories壹哺,設(shè)置的Gson,則會(huì)調(diào)用GsonConverterFactory的responseBodyConverter方法煞聪;
* 返回GsonResponseBodyConverter類斗躏,這里將在后面響應(yīng)回調(diào)分析中使用到。
*/
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
// 遍歷方法注解,這里會(huì)解析自定義接口里的方法注解并獲取對(duì)應(yīng)的value啄糙,為最后創(chuàng)建請(qǐng)求okhttp3.Call準(zhǔn)備參數(shù)
parseMethodAnnotation(annotation);
}
// 是否指定了請(qǐng)求方式
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 校驗(yàn)請(qǐng)求方式與編碼方式是否不合理笛臣。FormUrlEncoded和Multipart這兩種編碼方式必須使用在有請(qǐng)求體的請(qǐng)求方式中,如:@POST隧饼,@PUT
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).");
}
}
// 下面是方法參數(shù)注解解析并獲取其對(duì)應(yīng)的value沈堡,方法參數(shù)類型不能是泛型和通配符
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.");
}
// 這里parseParameter方法會(huì)調(diào)用到Retrofit中requestBodyConverter方法
// 即GsonRequestBodyConverter類中的convert方法,進(jìn)行數(shù)據(jù)序列化燕雁。
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
// 下面一些是判斷方法參數(shù)注解與請(qǐng)求方式诞丽、編碼方式是否匹配或沖突
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.");
}
// 最終返回ServiceMethod實(shí)例對(duì)象
return new ServiceMethod<>(this);
}
}
......
}
GsonRequestBodyConverter
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
5、RxJava2CallAdapter
這里根據(jù)設(shè)置生成相對(duì)應(yīng)的RxJava的被觀察者對(duì)象
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
......
@Override public Object adapt(Call<R> call) {
// 這里我們只考慮異步的情況拐格,同步基本一致僧免。生成CallEnqueueObservable對(duì)象,call為OkHttpCall
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
// 指定運(yùn)行線程捏浊,RxJava2CallAdapterFactory.createWithScheduler(Scheduler)指定創(chuàng)建
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
}
6懂衩、CallEnqueueObservable
RxJava的方法調(diào)用,當(dāng)被觀察者調(diào)用.subscribe()
訂閱之后金踪,會(huì)調(diào)用到里面的subscribeActual()
方法浊洞。
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
......
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<T> callback = new retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<>(call, observer);
observer.onSubscribe(callback);
// 這里是將call加入隊(duì)列,并傳入下面的CallCallback對(duì)象胡岔,異步請(qǐng)求法希。前面我們說(shuō)過(guò)這歌call對(duì)象是OkHttpCall。
call.enqueue(callback);
}
private static final class CallCallback<T> implements Disposable, Callback<T> {
......
//下面是正確和失敗回調(diào)靶瘸,即調(diào)用onNext和onError方法
@Override public void onResponse(Call<T> call, Response<T> response) {
if (disposed) return;
try {
observer.onNext(response);
if (!disposed) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
......
}
}
@Override public void onFailure(Call<T> call, Throwable t) {
if (call.isCanceled()) return;
try {
observer.onError(t);
} catch (Throwable inner) {
......
}
}
}
}
7苫亦、OkHttpCall
上面call.enqueue(callback)
實(shí)際走的就是OkHttpCall的enqueue方法。
final class OkHttpCall<T> implements Call<T> {
......
@Override
public void enqueue(final Callback<T> callback) {
// 回調(diào)非空判斷
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
// 同步鎖怨咪,創(chuàng)建真正發(fā)起網(wǎng)絡(luò)請(qǐng)求的okhttp3.Call著觉,會(huì)ServiceMethod類里toCall方法
synchronized (this) {
// 這里會(huì)對(duì)請(qǐng)求是否執(zhí)行過(guò)判斷,也就是說(shuō)代理對(duì)象方法里生成的OkHttpCall只能執(zhí)行一次
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
// 這里就轉(zhuǎn)到了OkHttp網(wǎng)絡(luò)請(qǐng)求框架惊暴,加入到請(qǐng)求隊(duì)列里面。
// 最后回調(diào)回調(diào)用CallEnqueueObservable中的CallCallback趁桃,即onNext或onError方法
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 這里是解析響應(yīng)數(shù)據(jù)方法
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
try {
callback.onResponse(retrofit2.OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(retrofit2.OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
......
private okhttp3.Call createRawCall() throws IOException {
// 調(diào)用的是ServiceMethod里面的toCall()方法
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
}
下面我們看下異步請(qǐng)求的回調(diào)辽话,這里只分析成功回調(diào),失敗回調(diào)是一樣的卫病。
在上面enqueue方法回調(diào)中有parseResponse(rawResponse)
這么一行代碼油啤,它做的就是解析響應(yīng)數(shù)據(jù)的功能。
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
// 這里是核心代碼
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
ServiceMethod類中toResponse方法:
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
這里直接分析核心代碼T body = serviceMethod.toResponse(catchingBody);
蟀苛,通過(guò)源碼可以看到益咬,最終其調(diào)用的是Retrofit配置時(shí)設(shè)置的converterFactories類的convert方法,返回設(shè)定的對(duì)象帜平,即反序列化響應(yīng)數(shù)據(jù)幽告。
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
8梅鹦、ExecutorCallAdapterFactory
如果我們沒(méi)有添加CallAdapterFactory請(qǐng)求適配器,則會(huì)使用Android平臺(tái)默認(rèn)請(qǐng)求適配器ExecutorCallAdapterFactory冗锁,調(diào)用enqueue方法時(shí)會(huì)走ExecutorCallbackCall中的enqueue方法齐唆,然后執(zhí)行OkHttpCall的enqueue方法,代碼如下:
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
// 這里的delegate就是OkHttpCall冻河,最終還是走到OkHttpCall的enqueue方法
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(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, t);
}
});
}
});
}
9箍邮、BuiltInConverters
如果沒(méi)有添加ConverterFactory,則會(huì)使用默認(rèn)的BuiltInConverters進(jìn)行requestBody序列化和responseBody反序列化叨叙。當(dāng)然锭弊,在BuiltInConverters還存在一個(gè)重要的類ToStringConverter,不管有沒(méi)有額外添加ConverterFactory擂错,其在ServiceMethod進(jìn)行注解解析時(shí)都會(huì)使用到味滞,具體參見(jiàn)ServiceMethod類中的ParameterHandler<?> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation)
方法。
final class BuiltInConverters extends Converter.Factory {
// 響應(yīng)數(shù)據(jù)反序列化轉(zhuǎn)換器
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
// 根據(jù)要求響應(yīng)數(shù)據(jù)類型的不同马昙,返回不同的converter
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? retrofit2.BuiltInConverters.StreamingResponseBodyConverter.INSTANCE
: retrofit2.BuiltInConverters.BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return retrofit2.BuiltInConverters.VoidResponseBodyConverter.INSTANCE;
}
return null;
}
// 請(qǐng)求體數(shù)據(jù)序列化轉(zhuǎn)化器
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return retrofit2.BuiltInConverters.RequestBodyConverter.INSTANCE;
}
return null;
}
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final retrofit2.BuiltInConverters.VoidResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.VoidResponseBodyConverter();
@Override public Void convert(ResponseBody value) {
// 不需要返回桃犬,直接close,返回null
value.close();
return null;
}
}
// RequestBody請(qǐng)求體轉(zhuǎn)換器
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final retrofit2.BuiltInConverters.RequestBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.RequestBodyConverter();
@Override public RequestBody convert(RequestBody value) {
return value;
}
}
// 流轉(zhuǎn)換器
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final retrofit2.BuiltInConverters.StreamingResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.StreamingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) {
return value;
}
}
// 容器轉(zhuǎn)換器
static final class BufferingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final retrofit2.BuiltInConverters.BufferingResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.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();
}
}
}
// 轉(zhuǎn)換成String
static final class ToStringConverter implements Converter<Object, String> {
static final retrofit2.BuiltInConverters.ToStringConverter
INSTANCE = new retrofit2.BuiltInConverters.ToStringConverter();
@Override public String convert(Object value) {
return value.toString();
}
}
}
注意事項(xiàng)
通過(guò)源碼的分析行楞,發(fā)現(xiàn)一些特別需要注意的事項(xiàng):
1攒暇、必須指定一個(gè)請(qǐng)求方式,并且不能設(shè)置兩個(gè)或兩個(gè)以上子房,請(qǐng)求方式有:@POST形用、@GET、@DELETE证杭、@HEAD田度、@PATCH、@PUT解愤、@OPTIONS镇饺、@HTTP;
2送讲、Retrofit配置時(shí)設(shè)置的baseUrl與設(shè)置請(qǐng)求方式對(duì)應(yīng)的relativeUrl奸笤,結(jié)合后要是一個(gè)合理的url,不能同時(shí)relativeUrl為null哼鬓,而又不添加@Url监右;
3、返回?cái)?shù)據(jù)類型不能是Retrofit中的Response
或okhttp3.Response
异希;
4健盒、請(qǐng)求過(guò)程中生成OkHttpCall
對(duì)象,只能調(diào)用一次請(qǐng)求,不能重復(fù)調(diào)用扣癣;
5惰帽、默認(rèn)響應(yīng)數(shù)據(jù)返回ResponseBody
, 請(qǐng)求體@Body
可使用RequestBody
搏色,當(dāng)使用自定義實(shí)體bean時(shí)善茎,不管做為@Body值還是作為響應(yīng)數(shù)據(jù)類型都必須添加一個(gè)ConverterFactory,如常用的GsonConverterFactory
频轿;
6垂涯、注解的使用不能胡亂搭配,比如:@Multipart和@isFormEncoded與@GET等沒(méi)有請(qǐng)求體的請(qǐng)求方式一起使用航邢,再者添加了@Multipart耕赘,在參數(shù)里面必須要有@Part注解。具體的可以分析ServiceMethod類中的parseParameterAnnotation
方法膳殷。
總結(jié)
????????這次分析以Retrofit使用流程為主線操骡,熟悉Retrofit的工作機(jī)制以及一些注意事項(xiàng)。Retrofit中使用了幾種設(shè)計(jì)模式:構(gòu)造者模式(Builder)赚窃、工廠模式(Factory)册招、策略模式(不同的CallAdapter和Converter)、觀察者模式等等勒极,這些都是在以后的工作中可以值得借鑒的地方是掰。還有就是注解的使用,這是一個(gè)很好的范例辱匿,基本上注解使用和解析的相關(guān)知識(shí)全部都涉及到了键痛,可以閱讀一下文章開(kāi)始推薦的Java-Type體系,是兩篇值得一讀好文章匾七。
????????以上就是本次分析的全部?jī)?nèi)容絮短,由于個(gè)人能力有限,如有不足或錯(cuò)誤的地方昨忆,敬請(qǐng)諒解丁频。