天天看点

带你一步步剖析Retrofit-源码解析:一款基于-OkHttp-实现的网络请求框架

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

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 方法,则直接传入

CallAdapter

及 Converter,创建

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

。一般来说这个

带你一步步剖析Retrofit-源码解析:一款基于-OkHttp-实现的网络请求框架

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 {