使用 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

这里不展开说,使用 构建者模式,可以按需配置多个属性,常见的有 baseUrladdCallAdapterFacotryaddConverterFactoryclient 等,生成最终的 Retrofit 对象;

create动态代理

这个是核心方法,我们平时写的接口需要通过该方法来生成具体的实例,create这个方法内部必然实现了通用的逻辑;

image-yrse.png

create

看源码可以知道:

  1. 调用 validateServiceInterface 方法验证接口是否正确编写;

  2. 返回了一个 动态代理 对象,主要还是匿名内部类 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

该方法检查传入的接口是否符合规范,如果不符合规范则直接抛出异常

  1. 是否为 interface

     if (!service.isInterface()) {
         throw new IllegalArgumentException("API declarations must be interfaces.");
     }
  2. 检查接口是否为泛型,并检查所有的继承的接口:

     // 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());
     }
  3. 如果在 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

serviceMethodCacheConcurrentHashMap<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);
     }
 }

这里的流程有三个值得注意的方法或对象:

  • createCallAdapter

  • createResponseConverter

  • Retrofit.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 对应 AndroidMainExecutordelegate 对应上面传入的 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 实际上是将 callAdapterconverterfactory 封装到一个 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 中被判断,如果存在该注解则不会传递 callbackExecutorAndroidMainExecutor,交给协程的调度器去处理;

到最后会根据挂起函数的返回值是 Response 还是响应体对应的类型,分别返回 SuspendForResponseSuspendForBody

和挂起函数不同,非挂起函数返回的是 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 实例中的 callAdapterconverterFactorycallFacotry ,将生成网络请求并发送的过程封装为一个 HttpServiceMethod

通过 HttpService#invoke 拿到方法的参数,结合解析到的方法信息,生成 Okhttp3.Request 交给 OkHttpClient 异步发送,拿到响应后使用 converterFactory 对响应体反序列化为对应的返回类型对象,经过 callAdapterFactory 对结果进行包装,比如 DefaultCallAdapterFactory 就将响应体包装成 ExecutorCallbackCall,能够在响应返回时切换回主线程;