使用 Retrofit2 很简单,只需要声明一个接口,用注解声明其请求方法、方法参数和返回类型,就能使用了,不需要编写额外的代码,相较于 OkHttp原始发送请求的繁琐步骤,Retrofit2 帮我们将其省略并自动组装请求;
下面是简单的例子
interface TestApi {
@GET("/test")
fun getTest(): Call<String>
@GET("/test")
suspend fun suspendGetTest(): String
}
fun main() {
val retrofit = Retrofit.Builder()
.client(
OkHttpClient()
)
.baseUrl("custom_url")
.build()
val api = retrofit.create(TestApi::class.java)
// 回调形式
api.getTest().enqueue(object : Callback<String> {
override fun onResponse(call: Call<String>, response: Response<String>) {
}
override fun onFailure(call: Call<String>, t: Throwable) {
}
})
// 协程形式
GlobalScope.launch {
api.suspendGetTest()
}
}Retrofit2-Builder
这里不展开说,使用 构建者模式,可以按需配置多个属性,常见的有 baseUrl 、addCallAdapterFacotry 、addConverterFactory、client 等,生成最终的 Retrofit 对象;
create动态代理
这个是核心方法,我们平时写的接口需要通过该方法来生成具体的实例,create这个方法内部必然实现了通用的逻辑;

create
看源码可以知道:
调用
validateServiceInterface方法验证接口是否正确编写;返回了一个 动态代理 对象,主要还是匿名内部类
InvocationHandler的实现部分
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable 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);
}
args = args != null ? args : emptyArgs;
Reflection reflection = Platform.reflection;
return reflection.isDefaultMethod(method)
? reflection.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(service, method).invoke(proxy, args);
}
});
}validateServiceInterface
该方法检查传入的接口是否符合规范,如果不符合规范则直接抛出异常
是否为 interface
if (!service.isInterface()) { throw new IllegalArgumentException("API declarations must be interfaces."); }检查接口是否为泛型,并检查所有的继承的接口:
// BFS 逻辑 Deque<Class<?>> check = new ArrayDeque<>(1); check.add(service); while (!check.isEmpty()) { Class<?> candidate = check.removeFirst(); // 获得泛型参数列表,如果不为空则表示是泛型 if (candidate.getTypeParameters().length != 0) { StringBuilder message = new StringBuilder("Type parameters are unsupported on ").append(candidate.getName()); if (candidate != service) { message.append(" which is an interface of ").append(service.getName()); } throw new IllegalArgumentException(message.toString()); } // 将其继承的接口加入队列,继续检查 Collections.addAll(check, candidate.getInterfaces()); }如果在 Builder 时设置了
validateEagerly,还会对方法进行加载if (validateEagerly) { Reflection reflection = Platform.reflection; for (Method method : service.getDeclaredMethods()) { // 不是默认方法 && 不是静态方法 && 不是编译器生成的方法 if (!reflection.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers()) && !method.isSynthetic()) { // 加载 loadServiceMethod(service, method); } } }
loadServiceMethod
serviceMethodCache 是 ConcurrentHashMap<Method, Object> 接口,用于存放已经加载过的方法 ServerMethod 以及正在解析该方法的锁;
ServiceMethod<?> loadServiceMethod(Class<?> service, Method method) {
while (true) {
// 从缓存中查找
Object lookup = serviceMethodCache.get(method);
if (lookup instanceof ServiceMethod<?>) {
// 缓存命中
return (ServiceMethod<?>) lookup;
}
// 没有锁或者缓存,则需要先进行解析;
// 如果不为空,则为锁,说明当前 method 正在解析
if (lookup == null) {
// 加锁
Object lock = new Object();
synchronized (lock) {
// 同步操作,先将锁放进缓存
lookup = serviceMethodCache.putIfAbsent(method, lock);
if (lookup == null) { // 双重检查锁
ServiceMethod<Object> result;
try {
// 解析注解
result = ServiceMethod.parseAnnotations(this, service, method);
} catch (Throwable e) {
// 出现问题移除锁,并抛出问题
serviceMethodCache.remove(method);
throw e;
}
// 方法缓存
serviceMethodCache.put(method, result);
return result;
}
}
}
// 等待锁释放
synchronized (lookup) {
Object result = serviceMethodCache.get(method);
if (result == null) {
// 其他线程解析失败,在当前线程重试,失败了则直接抛出异常
continue;
}
return (ServiceMethod<?>) result;
}
}
}
ServiceMethod#parseAnnotations
RequestFactory.parseAnnotations 会解析方法所带的注解以及参数的注解,形成一个请求所需要的完整信息
主要检查方法的返回值是否支持解析,调用Utils.hasUnresolvableType(returnType) 检查:
对于泛型的嵌套类型,会递归检测;
不支持通配符,比如
?、? super Number和? extends Number不支持泛型参数,比如
Call<T>
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Class<?> service, Method method) {
// 对方法的注解、参数注解进行解析,得到最终的结果
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, service, method);
// 获取到方法的返回值
Type returnType = method.getGenericReturnType();
// 判断是否支持方法的返回值
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
// 返回值为 void
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
HttpServiceMethod#parseAnnotations
Java 怎么判断 Kotlin 的函数是否为 suspend 函数?
Kotlin 的挂起函数编译为 Java 后,会在函数的最后加上
Continuation参数,用来恢复挂起点;因此通过判断最后一个参数是不是 Continuation 就能判断是不是 suspend 函数了
如果是 Kotlin 挂起函数,
会通过判断最后一个参数,也就是
Continuation泛型参数(编译后的实际函数):是否为 Response:会将响应对象返回
是否为 Call:抛出异常,suspend 不能结合 Call 一起使用
给方法的注解添加
@SkipCallback注解;
随后是对方法的返回值进行一系列的检查:
不是 okhttp3.Response 类型,而是 retrofit.Response 类型
retrofit.Response 没有指定具体的泛型参数
HEAD 请求方法的函数返回值需要是 Unit 或 Void
最后根据是否为挂起函数、挂起函数的返回值类型返回不同的 HttpServiceMethod 具体子类
非挂起函数:
CallAdapted挂起函数且返回类型为 Response:
SuspendForResponse挂起函数且返回类型为响应体对应的类型:
SuspendForBody
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// 这个值的判断是通过函数的最后一个参数是不是为 Continuation 来判断的
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
boolean continuationIsUnit = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType =
Utils.getParameterLowerBound(
0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
// 判断 Continuation<Response<T>> 情况,判断其返回值是否为响应对象
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// 检查 Continuation<Call<T>> 的情况,不支持这样使用
if (getRawType(responseType) == Call.class) {
throw methodError(
method,
"Suspend functions should not return Call, as they already execute asynchronously.\n"
+ "Change its return type to %s",
Utils.getParameterUpperBound(0, (ParameterizedType) responseType));
}
continuationIsUnit = Utils.isUnit(responseType);
}
// 先用 Call 包装一下,到时候通过 @SkipCallback 来直接返回值
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
// 给这个方法的注解添加上 @SkipCallback
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
// 这里对返回类型 Call 做对应的转换
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?");
}
// Response类型需要指定泛型
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// 对 HEAD 请求方法进行检查,判断其是否为空返回值 Void 或者 Unit
if (requestFactory.httpMethod.equals("HEAD")
&& !Void.class.equals(responseType)
&& !Utils.isUnit(responseType)) {
throw methodError(method, "HEAD method must use Void or Unit as response type.");
}
// 拿到 Converter 将响应体的内容反序列化成对象
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
// okhttpClient
okhttp3.Call.Factory callFactory = retrofit.callFactory;
// 非挂起函数
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
// 挂起函数且返回类型为 Response<T>
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
// 挂起函数且返回类型为具体的某个类型
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable,
continuationIsUnit);
}
}这里的流程有三个值得注意的方法或对象:
createCallAdaptercreateResponseConverterRetrofit.callFactory
往下看
HttpServiceMethod#createCallAdapter
这个方法和构建 Retrofit 时设置 addCallAdapterFactory 相关
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);CallAdapter 的作用主要是让开发者可以自定义将 Call 类型的返回值转换成自己想要的返回类型;
在创建 Retrofit 时优先将通过 addCallAdapterFactory 添加到列表,然后将默认的 DefaultCallAdapterFactory 添加到列表,结合下面的逻辑,可以知道优先使用开发者自定义的,最后才用默认的;
如果没有添加的话,就会使用默认的
DefaultCallAdapterFactory
// Retrofit
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(
@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
...
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
}平时非特殊需求,一般是没有添加这个 CallAdapter 的,所以调用的是 DefaultCallAdapterFactory:
仅针对 Call 类型的返回值进行解析;(在上面无论是挂起函数还是非挂起函数,在处理过程中都会将返回类型统一为
Call)通过判断 是否存在
@SkipCallback注解来传递Executor,如果不存在则为 null,否则为
callbackExecutor(如果没有主动设置的话,默认是Platform.callbackExecutor,Android的是AndroidMainExecutor,实际上是一个主线程 Looper 的 Handler)
从上面可以知道 Kotlin 的挂起函数会添加一个 @SkipCallback 的注解,同时挂起函数(协程)有自己的 dispatcher,因此不需要设置 callbackExecutor:
// DefaultCallAdapterFactory
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 不是 Call 返回类型不处理
if (getRawType(returnType) != Call.class) {
return null;
}
// Call 没有指定具体类型
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
// 根据是否设置的 @SkipCallbackExecutor 来设置 callbackExecutor
// 因为协程有自己的dispatcher,因此不需要设置
// 对于其他情况即 Call 返回类型的需要设置;
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
// 这里的 Call 具体类型是 OkHttpCall
public Call<Object> adapt(Call<Object> call) {
// 转换操作,一般想要实现自定义的转换方式就是这样设置
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
接下来看这个 ExecutorCallbackCall 静态内部类,内部有一个 enqueue 方法;
这里的
executor对应AndroidMainExecutor,delegate对应上面传入的call参数,也就是需要被适配的call;
将
delegate#enqueue方法增强了,添加了传入的回调callback(这里的回调就是使用api方法时Call的回调)
ExecutorCallbackCall 将请求从子线程切换到主线程,因此可以在传入的回调中直接更新UI
// ExecutorCallbackCall
@Override
public void enqueue(final Callback<T> callback) {
delegate.enqueue(
// retrofit2.Callback
new Callback<T>() {
@Override
// retrofit2.Call
public void onResponse(Call<T> call, final Response<T> response) {
// 当有响应结果时,会交给 callbackExecutor,实际上就是向 Handler post 了一个 Runnable
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<T> call, final Throwable t) {
callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}这里是拿到 callAdapter,可以将返回类型转换为自己所需要的类型;
HttpServiceMeathod#createResponseConverter
嗯,熟悉的味道我知道,这个过程和上面 CallAdapter 过程一模一样;
这里的 Converter 是构建 Retrofit 需要传递的 addConverterFactory,比如 addConverterFactory(GsonConverterFactory.create()),很明显就是将响应体的内容反序列化成对象;
// HttpServiceMeathod
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
...
return retrofit.responseBodyConverter(responseType, annotations);
...
}
// Retrofit
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
// Retrofit
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
....
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;
}
}
...
}
Retrofit.callFactory
这里的 callFactory 实际上就是传入的 client
public Builder client(OkHttpClient client) {
return callFactory(Objects.requireNonNull(client, "client == null"));
}
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = Objects.requireNonNull(factory, "factory == null");
return this;
}
HttpServiceMethod#invoke
经过上面这些过程,可以知道 loadServiceMethod 实际上是将 callAdapter、converter 和 factory 封装到一个 HttpServiceMethod 对象,让调用的方法可以明确发送请求、返回类型适配、响应体内容反序列这些流程;
随后还有一个重点,就是invoke 方法,是网络请求方法调用的开始:
封装成一个
OkHttpCall,通过adapt将返回类型进行对应的转换,取决于parseAnnotations的返回值的具体类型(多态)总的来说就是将返回的 Call 转换为方法设置的返回值类型
@Override
final @Nullable ReturnT invoke(Object instance, Object[] args) {
Call<ResponseT> call =
new OkHttpCall<>(requestFactory, instance, args, callFactory, responseConverter);
return adapt(call, args);
}看 CallAdapter 的实现,结合上面的 ExecutorCallbackCall,是调用了 Call#enqueue,在这里就是 OkHttpCall#enqueue
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
...
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}OkhttpCall 实际上就是用 OkHttpClient 异步发送请求,并对响应体调用 converter.convert (如果设置了)进行反序列化;
// OkHttpCall
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
Throwable failure;
// 省略 call 赋值代码
// call 是调用了 callFactory.newCall,实际上是 OkhttpClient#newCall
// 从下面开始就是 Okhttp 发送网络请求的开始了
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 会调用 converter.convert 进行反序列化数据
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
...
}
...
});
}RequestFactory
该类是解析请求方法的核心,解析方法注解和方法参数的注解,得到该请求方法设置的请求信息,比如请求方法、URL、参数名等
在 create 的流程中,ServiceMethod#parseAnnotations 会调用到该方法:
static RequestFactory parseAnnotations(Retrofit retrofit, Class<?> service, Method method) {
return new Builder(retrofit, service, method).build();
}
Builder(Retrofit retrofit, Class<?> service, Method method) {
this.retrofit = retrofit;
this.service = service;
this.method = method;
this.methodAnnotations = method.getAnnotations(); // 方法注解信息
this.parameterTypes = method.getGenericParameterTypes(); // 方法参数类型信息
this.parameterAnnotationsArray = method.getParameterAnnotations(); // 方法参数注解信息
}在 OkhttpCall 实例化时,同时拿到处理出来的请求方法信息和请求方法的参数;
OkHttpCall(
RequestFactory requestFactory,
Object instance,
Object[] args,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory; // 请求方法的信息
this.instance = instance;
this.args = args; // 请求方法的参数
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
在 OkhttpCall 的 enqueue 方法中,最终会调用到该方法,形成最终的 OkHttp.Request:
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(instance, args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
okhttp3.Request create(@Nullable Object instance, Object[] args) throws IOException {
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args.length;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException(
"Argument count ("
+ argumentCount
+ ") doesn't match expected count ("
+ handlers.length
+ ")");
}
RequestBuilder requestBuilder =
new RequestBuilder(
httpMethod,
baseUrl,
relativeUrl,
headers,
contentType,
hasBody,
isFormEncoded,
isMultipart);
if (isKotlinSuspendFunction) {
// The Continuation is the last parameter and the handlers array contains null at that index.
argumentCount--;
}
List<Object> argumentList = new ArrayList<>(argumentCount);
for (int p = 0; p < argumentCount; p++) {
argumentList.add(args[p]);
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder
.get()
.tag(Invocation.class, new Invocation(service, instance, method, argumentList))
.build();
}
适配Kotlin的挂起函数
在上面的 HttpServiceMethod#parseAnnotations 中,会对函数的最后一个参数是否为 Continuation 类型来判断是否为 Kotlin 的挂起函数,这是因为 Kotlin 的挂起函数在编译成 Jvm 时会将返回值 T 替换成方法的最后一个参数 Continuation<T>(编译器帮了我们做回调这一步)
如果是挂起函数,在 HttpServiceMethod#parseAnnotations 部分还会添加@SkipCallback 注解,该注解在 DefaultCallAdatperFactory#adapt 中被判断,如果存在该注解则不会传递 callbackExecutor即 AndroidMainExecutor,交给协程的调度器去处理;
到最后会根据挂起函数的返回值是 Response 还是响应体对应的类型,分别返回 SuspendForResponse 和 SuspendForBody;
和挂起函数不同,非挂起函数返回的是 CallAdapted,最终会经过 OkHttpClient 的 enqueue 异步操作;
SuspendForResponse
static final class SuspendForResponse<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
...
@Override
protected Object adapt(Call<ResponseT> call, Object[] args) {
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation<Response<ResponseT>> continuation =
(Continuation<Response<ResponseT>>) 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);
}
}
}进入 Kotlin 编写的代码,可以发现是 Call 的扩展函数,还是挂起函数
看代码可以知道启动了一个协程,最终还是调用了 Call#enqueue 在上面的流程分析中为 OkHttpCall#enqueue,交给了 OkHttpClient 的线程池执行;
当拿到结果后,会调用 continuation.resume 返回结果;
suspend fun <T> Call<T>.awaitResponse(): Response<T> {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
continuation.resume(response)
}
override fun onFailure(call: Call<T>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}为什么 Java 调用 Kotlin 的
awaitResponse需要传入 call 和 continuation 两个参数,而 Kotlin 的方法声明并没有这两个参数?
第一个参数是 Kotlin 的扩展函数编译后的结果,扩展函数实际上是一个静态方法,将一个对象传入进行处理,本质上也是在外部访问对象,因此扩展函数无法访问对象的私有属性和方法;
第二个参数是 Kotlin 的挂起函数编译后的结果,挂起函数会将其返回值包装成一个
Continuation,放入方法参数的最后一个,当有别的挂起函数需要该函数的结果时,通过continuation.resume返回调用者挂起函数,对应挂起点恢复;
SuspendForBody
整体上和 SuspendForResponse 流程相似,只是判断返回的类型是否为可空和 Unit 来分别调用不同的方法:
这些方法的过程都是类似的,交给
OkHttpClient的线程池去异步发送请求,通过continuation.resume从回调中拿到结果;不同之处在于有没有判断
response.body是否为空;
static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
private final boolean isNullable;
private final boolean isUnit;
@Override
protected Object adapt(Call<ResponseT> call, Object[] args) {
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
try {
if (isUnit) {
//noinspection unchecked Checked by isUnit
return KotlinExtensions.awaitUnit((Call<Unit>) call, (Continuation<Unit>) continuation);
} else if (isNullable) {
return KotlinExtensions.awaitNullable(call, continuation);
} else {
return KotlinExtensions.await(call, continuation);
}
} catch (VirtualMachineError | ThreadDeath | LinkageError e) {
// Do not attempt to capture fatal throwables. This list is derived RxJava's `throwIfFatal`.
throw e;
} catch (Throwable e) {
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
}
Kotlin 的代码
@JvmName("awaitUnit")
suspend fun Call<Unit>.await() {
@Suppress("UNCHECKED_CAST")
(this as Call<Unit?>).await()
}
@JvmName("awaitNullable")
suspend fun <T : Any> Call<T?>.await(): T? {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback<T?> {
override fun onResponse(call: Call<T?>, response: Response<T?>) {
if (response.isSuccessful) {
continuation.resume(response.body())
} else {
continuation.resumeWithException(HttpException(response))
}
}
override fun onFailure(call: Call<T?>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
suspend fun <T : Any> Call<T>.await(): T {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful) {
val body = response.body()
if (body == null) {
val invocation = call.request().tag(Invocation::class.java)!!
val service = invocation.service()
val method = invocation.method()
val e = KotlinNullPointerException(
"Response from ${service.name}.${method.name}" +
" was null but response body type was declared as non-null",
)
continuation.resumeWithException(e)
} else {
continuation.resume(body)
}
} else {
continuation.resumeWithException(HttpException(response))
}
}
override fun onFailure(call: Call<T>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
总结
Refrofit2 通过动态代理,拿到调用的方法信息,解析方法的注解、参数注解和返回值,拿到 Refrofit 实例中的 callAdapter、converterFactory 和 callFacotry ,将生成网络请求并发送的过程封装为一个 HttpServiceMethod
通过 HttpService#invoke 拿到方法的参数,结合解析到的方法信息,生成 Okhttp3.Request 交给 OkHttpClient 异步发送,拿到响应后使用 converterFactory 对响应体反序列化为对应的返回类型对象,经过 callAdapterFactory 对结果进行包装,比如 DefaultCallAdapterFactory 就将响应体包装成 ExecutorCallbackCall,能够在响应返回时切换回主线程;