int question = value.indexOf(’?’);
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(method, "URL query string “%s” must not have replace block. "+ “For dynamic query parameters use @Query.”, queryParams);
}
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
這裡實際上就是對不同 HTTP 請求方式和 Path 進行了指派,同時通過正規表達式保證了這個接口的 Path 中沒有包含參數。
對 Headers 的處理
private Headers parseHeaders(String[] headers) {
Headers.Builder builder = new Headers.Builder();
for (String header : headers) {
int colon = header.indexOf(’:’);
if (colon == -1 || colon == 0 || colon == header.length() - 1) {
throw methodError(method,
“@Headers value must be in the form “Name: Value”. Found: “%s””, header);
}
String headerName = header.substring(0, colon);
String headerValue = header.substring(colon + 1).trim();
if (“Content-Type”.equalsIgnoreCase(headerName)) {
try {
contentType = MediaType.get(headerValue);
} catch (IllegalArgumentException e) {
throw methodError(method, e, “Malformed content type: %s”, headerValue);
}
} else {
builder.add(headerName, headerValue);
}
}
return builder.build();
}
而對于 Headers 則是将傳遞進來的
Headers
清單解析為了對應的
Headers
對象。
對方法參數的處理
最後我們看看對方法參數的處理:
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
// 對每個注解通過 parseParameterAnnotation 進行解析
ParameterHandler<?> annotationAction =
parseParameterAnnotation(p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(method, p,
“Multiple Retrofit annotations found, only one allowed.”);
}
result = annotationAction;
}
}
if (result == null) {
// 在協程的情況下對進行特殊處理
if (allowContinuation) {
try {
if (Utils.getRawType(parameterType) == Continuation.class) {
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, “No Retrofit annotation found.”);
}
return result;
}
而
parseParamterAnnotation
方法的代碼太長了,這裡就不再貼了,它對方法的每個注解都進行了獨有的處理,并傳回了對應的
ParamterHandler
。
可以發現,
RequestFactory.parseAnnotations
的主要作用就是完成對方法注解資訊的解析,進而用于産生對應的
Request
。
ServiceMethod 的建立
之後我們接着看看 HttpServiceMethod.parseAnnotations
:
HttpServiceMethod.parseAnnotations
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
// 如果方法是 kotlin 中的 suspend 方法
Type[] parameterTypes = method.getGenericParameterTypes();
// 擷取 Continuation 的範型參數,它就是 suspend 方法的傳回值類型
Type responseType = Utils.getParameterLowerBound(0,
(ParameterizedType) parameterTypes[parameterTypes.length - 1]);
// 如果 Continuation 的範型參數是 Response,則說明它需要的是 Response,那麼将 continuationWantsResponse 置為 true;
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// Unwrap the actual body type from Response.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
// 否則擷取方法傳回值的範型參數,即為請求需要的傳回值的類型
adapterType = method.getGenericReturnType();
}
// 通過 createCallAdapter 方法建立 CallAdapter 對象
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(method, “’”
- getRawType(responseType).getName()
-
“’ is not a valid response body type. Did you mean ResponseBody?”);
}
if (responseType == Response.class) {
throw methodError(method, “Response must include generic type (e.g., Response)”);
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals(“HEAD”) && !Void.class.equals(responseType)) {
throw methodError(method, “HEAD method must use Void as response type.”);
}
// 通過 createResponseConverter 方法建立 Converter對象
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 不是suspend方法的話則直接建立并傳回一個 CallAdapted 對象
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call>) callAdapter,
continuationBodyNullable);
}
}
這裡的代碼非常非常長,大緻可歸納為下面的步驟:
1. 如果這個方法是 Kotlin 中的 suspend 方法,由于由協程實作,是以需要擷取
Continuation
的範型參數,這個參數就是請求傳回值的真正類型。
2. 如果
方法傳回值是
suspend
,則說明它需要的是 Response 而不是具體的類型,那麼将
Response
continuationWantsResponse
置為 true;
3. 如果不是
方法,則傳回值的範型參數的類型就是請求傳回值的真正類型(
suspend
則
Call<ReturnType>
ReturnType
才是真正經過轉換後需要的類型)。
4. 通過
方法建立
createCallAdapter
對象,它是用于将
CallAdapter
對象适配為需要的類型
Call<ResponseT>
ReturnT
對象的。
5. 拿到
後,擷取到了
CallAdapter
Response
的類型,并進行了校驗。
6. 通過
方法擷取
createResponseConverter
對象,它可以完成從
Converter
到
ResponseBody
類型
Response
ResponseT
的轉換。
7. 如果并非 Kotlin 的 suspend 方法,則直接傳入
及 Converter,建立
CallAdapter
CallAdapted
對象。
8. 否則根據 suspend 方法需要的是
還是具體的類型,分别傳回
Response
和
SuspendForResponse
對象。
SuspendForBody
可以發現,新版的 Retrofit 對 Kotlin 的協程進行了支援。
HttpServiceMethod.parseAnnotations
的主要作用就是建立
CallAdapter
以及 Converter 對象,并建構對應
HttpServiceMethod
。
CallAdapter
CallAdapter
是用于将
Call<R>
對象适配為需要的類型 T 對象的。它的聲明如下:
public interface CallAdapter<R, T> {
// 傳回 Response 的類型
Type responseType();
// 将 Call 轉換為 T 類型
T adapt(Call call);
}
我們先看看
createCallAdapter
方法是如何對它建立的:
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, “Unable to create call adapter for %s”, returnType);
}
}
它調用了
retrofit.callAdapter
方法:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
之後調用到
retrofit.nextCallAdapter
方法:
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
Objects.requireNonNull(returnType, “returnType == null”);
Objects.requireNonNull(annotations, “annotations == null”);
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
// 周遊 callAdapterFactories,嘗試建立 CallAdapter
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
// …不存在對應的 CallAdapterFactory,抛出異常
}
這裡實際上是周遊了建立 Retrofit 對象時傳遞的
CallAdapter.Factory
清單嘗試去建立
CallAdapter
。如果這些
CallAdapter.Factory
都無法處理這個對應的
returnType
以及
annotations
的話,則會抛出異常。(前面 Factory 的優先級更高)
Retrofit 中有一個預設的
CallAdapter
工廠
DefaultCallAdapterFactory
,它的優先級比所有自定義工廠要低,它在建立時會傳入一個
Executor
,我們可以看到它的 get 方法:
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
“Call return type must be parameterized as Call or Call<? extends Foo>”);
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call adapt(Call call) {
return executor == null
? call: new ExecutorCallbackCall<>(executor, call);
}
};
}
可以看到,在沒有
Executor
時,它不對 Call 進行修改,在有指定 Executor 時,則會将其包裝為
ExecutorCallbackCall
。一般來說這個

Executor 就是建立 Retrofit 時指定的
callbackExecutor
。
這個
callbackExecutor
實際上是用來指定調用
Callback
的線程的,進而使得
Callback
并不一定是在主線程被回調:
static final class ExecutorCallbackCall implements Call {
final Executor callbackExecutor;
final Call delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback callback) {
Objects.requireNonNull(callback, “callback == null”);
// 對 Callback 進行了包裝,通過 callbackExecutor 進行回調
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
callbackExecutor.execute(() -> {
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 call, final Throwable t) {
callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
// …
}
可以看到,這裡實際上隻是對 Callback 進行了包裝,通過傳遞的 Executor 進行回調,進而對
callbackExecutor
進行支援。
Converter
接着我們看看
Converter
類,它是一個接口,用于将類型 F 的資料轉換為類型 T:
public interface Converter<F, T> {
@Nullable T convert(F value) throws IOException;
// …
}
接着我們看看
createResponseConverter
是如何對它進行建立的:
private static Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, “Unable to create converter for %s”, responseType);
}
}
轉調到了
retrofit.responseBodyConverter
:
public Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
轉調到了
nextResponseBodyConverter
:
public Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
Objects.requireNonNull(type, “type == null”);
Objects.requireNonNull(annotations, “annotations == null”);
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
// 沒有找到對應的 ConverterFactory 進行處理,抛出異常
}
可以看到,這裡與
CallAdapter
工廠類似,周遊建立 Retrofit 時傳入的
Converter.Factory
清單,嘗試進行建立,如果沒有工廠能對其進行處理,抛出異常。(前面 Factory 的優先級更高)
Retrofit
中内置了兩個
Converter.Factory
,分别是
BuiltInConverters
以及
OptionalConverterFactory
。
其中
BuiltInConverters
的優先級比所有自定義工廠要高,以避免其他工廠覆寫它的方法,而
OptionalConverterFactory
的優先級比所有自定義工廠的優先級更低。
BuiltInConverters
中實作了多個轉換器如将
ResponseBody
轉換為 Void 或 Unit,将 Object 轉換為 String 等。
OptionalConverterFactory
是通過 platform 擷取到的
defaultConverterFactories
,它是為了支援 Java 8 的 Optional 而實作的,Optional 是 Java 8 引入的用來解決空指針異常的類。
ServiceMethod
接着我們看看之前建立的
ServiceMethod
類,它是一個抽象類,需要子類對 invoke 方法進行實作。
abstract class ServiceMethod {
abstract @Nullable T invoke(Object[] args);
}
它的子類就是前面提到的
HttpServiceMethod
HttpServiceMethod
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod {
@Override final @Nullable ReturnT invoke(Object[] args) {
Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call call, Object[] args);
}
HttpServiceMethod
的 invoke 方法非常簡單,它構造了一個
OkHttpCall
,然後通過 adapt 這個虛函數來實作對 Call 的轉換。它的子類隻需要實作 adapt 進而對 Call 進行轉換即可。
它共有三個子類,首先就是并非使用協程的情況下的
CallAdapted
類,另外兩個子類則是在使用協程的情況下為了配合協程的
SuspendForResponse
以及
SuspendForBody
類
CallAdapted
CallAdapted
類繼承自
HttpServiceMethod
類,并通過傳遞進來的
CallAdapter
對 Call 進行了轉換。
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected ReturnT adapt(Call call, Object[] args) {
return callAdapter.adapt(call);
}
}
SuspendForResponse
SuspendForResponse
類首先根據傳遞進來的 Call 構造了一個參數為
Response<ResponseT>
的
Continuation
對象然後通過 Kotlin 實作的
awaitResponse
方法将 call 的
enqueue
異步回調過程封裝為了一個 suspend 的函數。
static final class SuspendForResponse extends HttpServiceMethod<ResponseT, Object> {
private final CallAdapter<ResponseT, Call> callAdapter;
SuspendForResponse(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, Call> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected Object adapt(Call call, Object[] args) {
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation<Response> continuation =
(Continuation<Response>) args[args.length - 1];
// See SuspendForBody for explanation about this try/catch.
try {
return KotlinExtensions.awaitResponse(call, continuation);
} catch (Exception e) {
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
}
awaitResponse
方法如下:
suspend fun Call.awaitResponse(): Response {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
continuation.resume(response)
}
override fun onFailure(call: Call, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
可以看到,分别通過在
onResponse
和
onFailure
中調用
continuation.resume
和
continuation.resumeWithException
進而對協程進行支援。
SuspendForBody
而
SuspendForBody
則是根據傳遞進來的 Call 構造了一個
Continuation<ResponseT>
對象然後通過 Kotlin 實作的 await 或
awaitNullable
方法将 call 的
enqueue
異步回調過程封裝為了一個 suspend 的函數。
static final class SuspendForBody extends HttpServiceMethod<ResponseT, Object> {
private final CallAdapter<ResponseT, Call> callAdapter;
private final boolean isNullable;
SuspendForBody(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, Call> callAdapter, boolean isNullable) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
this.isNullable = isNullable;
}
@Override protected Object adapt(Call call, Object[] args) {
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation continuation = (Continuation) args[args.length - 1];
// Calls to OkHttp Call.enqueue() like those inside await and awaitNullable can sometimes
// invoke the supplied callback with an exception before the invoking stack frame can return.
// Coroutines will intercept the subsequent invocation of the Continuation and throw the
// exception synchronously. A Java Proxy cannot throw checked exceptions without them being
// in an UndeclaredThrowableException, it is intercepted and supplied to a helper which will
// force suspension to occur so that it can be instead delivered to the continuation to
// bypass this restriction.
try {
return isNullable
? KotlinExtensions.awaitNullable(call, continuation)
: KotlinExtensions.await(call, continuation);
} catch (Exception e) {
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
}
Call
Call 實際上是一個接口,它提供了
execute
、
enqueue
、
cancel
等接口用于實作請求,當我們需要請求一個接口的時候,隻需要調用其
enqueue
或
execute
方法即可。
public interface Call extends Cloneable {
Response execute() throws IOException;
void enqueue(Callback callback);
boolean isExecuted();
void cancel();
boolean isCanceled();
Call clone();
Request request();
}
從前面的過程中我們可以了解到,如果我們沒有傳入
CalAdapter
的話,預設情況下傳回的 Call 實際上是
OkHttpCall
對象,讓我們通過它來看看 Retrofit 如何基于
OkHttp
實作的網絡請求:
enqueue
首先讓我們看看
enqueue
的代碼:
@Override public void enqueue(final Callback callback) {
Objects.requireNonNull(callback, “callback == null”);
okhttp3.Call call;
Throwable failure;
// 加鎖,對狀态進行設定并通過 createRawCall 方法建立 okhttp3.Call
synchronized (this) {
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;
}
// 如果外界取消該任務,則調用 okhttp3.Call.cancel
if (canceled) {
call.cancel();
}
// 通過 okhttp3.Call.enqueue 将消息入隊
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response response;
try {
// 獲得結果後通過 parseResponse 進行解析
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
// 解析完成後通過 onResponse 進行回調
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
// 請求失敗調用 callFailure 回調失敗請求
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
enqueue
的代碼看似多,實際上比較簡單,主要分為以下幾步:
1. 加鎖,對執行狀态進行設定,若不存在 rawCall 則調用 createRawCall 方法建立 okhttp3.Call 對象。
2. 如果外界取消該任務,則調用 okhttp3.Call.cancel
3. 通過 okhttp3.Call.enqueue 将消息入隊
4. 若獲得 Response,則通過 parseResponse 方法對 Response 進行解析,解析完成後通過 onResponse 回調解析結果。
5. 若請求失敗,通過 callFailure 方法調用 onFailure 回調請求失敗。
可以發現一個小細節,Retrofit 對已經建立的
okhttp3.Call
進行了複用,避免了重複建立進而浪費效率。
execute
接着讓我們看看
execute
是如何實作的:
@Override public Response execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException(“Already executed.”);
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
,避免了重複建立進而浪費效率。**
execute
接着讓我們看看
execute
是如何實作的:
@Override public Response execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException(“Already executed.”);
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {