一. 使用用例
//步驟【1】
OkHttpclient client = new OkHttpClient.Builder().build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl("http://localhost:4567/")
.build();
@GET("/getName")
Call<ResponseBody> request(@Query("name") String name);
//步驟【2】
IService service = retrofit.create(IService.class);
Call<ResponseBody> call = service.request("test");
//步驟【3】
call.enqueue(new Callable() {
...
)
二. 源碼解析
1. Retrofit.Build
//一般情況下试和,Platform是Android
public Builder() {
this(Platform.get());
}
Builder(Platform platform) {
this.platform = platform;
converterFactories.add(new BuiltInConverters());
}
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;
//如果是Android平臺昌妹,則Executor的實際邏輯就是在當前主線程中runnable
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//如果是Android平臺耽梅,defaultCallAdapterFactory是ExecutorCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
//如果沒設置刹泄,默認沒有convert
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
//validateEagerly默認為false
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
- 如果沒有設置
CallAdapter
,對于Android平臺诊胞,默認使用ExecutorCallAdapterFactory
- 如果沒有設置
ConvertFactory
, 默認使用BuiltInConverters
2. Retrofit.create
public <T> T create(final Class<T> service) {
//校驗傳入的Class是不是Interface,且定義了至少一個方法
Utils.validateServiceInterface(service);
if (validateEagerly) {
//如果是Android平臺庸队,isDefaultMethod = false, 將service中所有method都生成對應的
//ServiceMethod類刁卜,并放入緩存(核心調用為【2.1】loadServiceMethod)
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 (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//Android平臺isDefaultMethod = false
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);
}
});
}
- 首先校驗傳入的Class是不是一個接口
- 因為默認的validateEagly = false, 所以不執(zhí)行eagerlyValidateMethods方法,該方法實質上根據(jù)接口中的所有方法生成每個方法相應的ServiceMethod逢唤,并放入緩存
- 創(chuàng)建動態(tài)代理(核心步驟)拉讯,以后每次調用接口的方法都會調用InvocationHandler.invoke(...)方法
2.1 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) {
//【2.2】
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
創(chuàng)建相應的ServiceMethod
類,并放入緩存
2.2 ServiceMethod.Builder
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
//獲取CallAdapter, 【2.2.1】
callAdapter = createCallAdapter();
//獲取Call<T>中T的具體類型
responseType = callAdapter.responseType();
//確保T并不是retrofit2.Response或者okhttp3.Response
if (responseType == Response.class||responseType == okhttp3.Response.class) {
...
}
//如果沒有設置Converter,默認的Converter是BuiltInConverter, 通過
//BuiltInConvert.responseBodyConverter返回Convert,
//如果Annotation中Streaming, 則返回StreamingResponseBodyConverter鳖藕,
//否則返回BufferingResponseBodyConverter
//【2.2.2】
responseConverter = createResponseConverter();
//處理方法的注釋, 【2.2.3】
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError(...);
}
//對于GET魔慷,HEAD等沒有body的請求,不允許出現(xiàn)@FormEncodedUrl或@MultiPart等注釋
if (!hasBody) {
if (isMultipart) {
throw methodError(..);
}
if (isFormEncoded) {
throw methodError(...);
}
}
//處理參數(shù)的注解, 【2.2.4】
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(...);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(...);
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError(...);
}
//GET, DELETE等方法不可以有@Body
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(...);
}
//有@FormUrlEncoded注釋則參數(shù)中至少有一個@Field注釋
if (isFormEncoded && !gotField) {
throw methodError(...);
}
//有@Multipart注釋著恩,參數(shù)中至少有一個@Part注釋
if (isMultipart && !gotPart) {
throw methodError(...);
}
return new ServiceMethod<>(this);
}
- 獲取CallAdapter
- 獲取Call<T>中T的具體類型院尔,并確保T并不是retrofit2.Reponse或okhttp3.Response
- 獲取Converter
- 處理方法注釋
- 注釋參數(shù)注釋
2.2.1 ServiceMethod.createCallAdapter
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
//返回值不能是TypeVariable和WildcardType
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(...);
}
//確保返回值不能是void
if (returnType == void.class) {
throw methodError(...);
}
Annotation[] annotations = method.getAnnotations();
try {
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) {
throw methodError(...);
}
}
2.2.1.1 Retrofit.callAdapter
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
//如果沒有顯示的設置蜻展,Android平臺的默認只有一個CallAdapter.Factory -> ExecutorCallAdapterFactory
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
throw new IllegalArgumentException(...);
}
2.2.1.2 ExecutorCallAdapterFactory.get()
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//確保返回值類型是Call
if (getRawType(returnType) != Call.class) {
return null;
}
//返回Call<T>的具體所指的類型
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 new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
2.2.2 ServiceMethod.createResponseConverter()
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) {
throw methodError(...);
}
}
2.2.2.1 Retrofit.responseBodyConverter
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
//如果沒有顯示設置, convertFactories里面只有BuiltInConverters
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
return (Converter<ResponseBody, T>) converter;
}
}
...
throw new IllegalArgumentException(...);
}
2.2.2.2 BuiltInConverters.responseBodyConverter
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
2.2.3 ServiceMethod.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;
}
}
parseMethodAnnotation
方法主要就是用過parseHttpMethodAndPath
方法設置ServiceMethhod
的請求方法邀摆,相對Url, 是否有body等選項
2.2.4 ServiceMethod.parseParameter
private ParameterHandler<?> parseParameter(int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
//核心調用
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(...);
}
result = annotationAction;
}
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
該方法中的核心調用parseParameterAnnotation
,這個方法的主要作用是根據(jù)參數(shù)的注解進行不同的處理纵顾,參數(shù)的注解可以是以下幾種:
- @Url
- @Path
- @Query
- @QueryName
- @QueryMap
- @Header
- @HeaderMap
- @Field
- @FieldMap
- @Part
- @PartMap
- @Body
2.3 ServiceMethod.callAdapter.adapter
ServiceMethod.callAdapter是通過ExcecutorAdapterFactory.get()
創(chuàng)建的一個匿名CallAdapter
, 其實現(xiàn)為:
new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
....
}
由此可以看出,最終真正返回的是ExecutorCallbackCall
, 其中delagate
是OkHttpCall
3. ExecutorCallbackCall.enqueue
@Override
public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
//實際是調用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()) {
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
3.1 OkHttpCall.enqueue
@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 {
//【3.1.1】
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
//調用okhttp3.Call.enqueue,后續(xù)走的就是okhttp請求的流程
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
//【3.1.2】
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();
}
}
});
}
3.1.1 OkHttpCall.createNewCall
private okhttp3.Call createRawCall() throws IOException {
//這里的args就是被動態(tài)代理的方法的參數(shù), 【3.1.2.1】
Request request = serviceMethod.toRequest(args);
//callFactory是OkHttpClient
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
OkHttpClient
同樣實現(xiàn)了okhttp3.Call.Factory
接口隧熙, 而通過步驟【1】和【2.2】的代碼可以看出, 這里的callFactory
就是OkHttpClient
,所以調用的是OkhttpClient.newCall
(實際返回一個okhttp3.RealCall
)
3.1.1.1 ServiceMethod.toRequest
Request toRequest(Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
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++) {
//不同參數(shù)的注釋有對應不同的handler, 以Query為例片挂,其handler是Query<T>
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
這個方法的核心調用在于handlers[p].apply
,不同的參數(shù)注釋幻林,對應這不同的ParameterHandler
,以@Query
為例贞盯,它所對應的ParammeterHandler
是Query<T>
, Query<T>.apply
的作用是將@Query
所修飾的參數(shù)轉為String
類型并添加到要請求的url的query string中
3.1.2 OkHttpCall.parseResponse
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;
}
}
3.1.3 ServiceMethod.toResponse
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
在之前【2.2.2】中可以得知, 如果沒有設置Converter沪饺,則使用默認的BuiltInConverter來獲取對應的response convert, 如果方法中有@Streaming
注釋躏敢,則responseConverter
是StreamingResponseBodyConverter
, 否則是BufferingResponseBodyConverter
, 一般情況下不會有@Streaming
注釋
3.1.4 Converter.convert
3.1.4.1 StreamingResponseBodyConverter
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
@Override
public ResponseBody convert(ResponseBody value) throws IOException {
return value;
}
}
3.1.4.2 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
static ResponseBody buffer(final ResponseBody body) throws IOException {
Buffer buffer = new Buffer();
body.source().readAll(buffer);
return ResponseBody.create(body.contentType(), body.contentLength(), buffer);
}