Retrofit源码解析

本文分析的源码基于retrofit:2.9.0

前言

Retrofit基于OkHttp,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装,它们的关系示意图如下:

image-20211223125633592

基本使用

首先添加依赖

    // Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    // Retrofit的Gson转换器
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

封装一个工具类

object ServiceCreator {
    private const val BASE_URL = "https://api.github.com"

    private val httpClient = OkHttpClient.Builder()

    private val builder = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(httpClient.build())
        .addConverterFactory(GsonConverterFactory.create())

    private val retrofit = builder.build()

    fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
}

写一个Retrofit的接口

interface IUser {
    @GET("/users/{nickname}")
    fun getUser(@Path("nickname") nickname: String): Call<User>
}

@GET中所填写的valueBaseUrl组成完整的路径,BaseUrl在构造Retrofit对象时已给出。

其中User类如下

data class User(var id: Long? = null, var name: String? = null)

网络请求代码如下

        val netRequestBn: Button = findViewById(R.id.net_request)
        netRequestBn.setOnClickListener {
            val iUser = ServiceCreator.create(IUser::class.java)
            iUser.getUser("giagor").enqueue(object : Callback<User> {
                override fun onResponse(call: Call<User>, response: Response<User>) {
                    val user = response.body()
                    Log.d(TAG, "$user")
                }

                override fun onFailure(call: Call<User>, t: Throwable) {
                    Log.d(TAG, "网络请求失败")
                }
            })
        }

进行网络请求后,我们可以看到下面的日志信息

D/MainActivity: User(id=57672520, name=Giagor)

上面展示了异步请求的方式。如果想要进行同步请求,则需要调用iUser.getUser("giagor").execute(),同步请求的情况下,要记得自己处理异常,比如使用try...catch包住上面的...execute()代码。

@Header注解的使用:

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();

@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username)

Headers不会互相覆盖,也就是有相同名字的Headers会一并被包含到请求中。也可以给方法的参数使用@Header注解,达到动态设置的目的,如下

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

如果authorizationnull@Header("Authorization")注解会被忽略,并不会被提交,否则会调用authorizationtoString方法作为@Header("Authorization")的值。

对于复杂的Header组合,也可以使用Map

@GET("user")
Call<User> getUser(@HeaderMap Map<String, String> headers)

如果有的Header需要添加到每个请求上面,就使用OkHttp的拦截器添加。

更多使用参考:

  1. Retrofit (square.github.io)
  2. Retrofit2 完全解析 探索与okhttp之间的关系_Hongyang-CSDN博客

Retrofit对象创建

Retrofit采用Builder模式构建,其中Retrofit的变量定义和构造方法如下:

public final class Retrofit {
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

  // 网络请求的工厂,作用是产生网络的请求器(Call)  
  final okhttp3.Call.Factory callFactory;
  // 网络请求的BaseUrl  
  final HttpUrl baseUrl;
  // 数据转换器工厂的集合  
  final List<Converter.Factory> converterFactories;
  // 网络请求适配器工厂的集合  
  final List<CallAdapter.Factory> callAdapterFactories;
  // 回调方法执行器  
  final @Nullable Executor callbackExecutor;
  // 是否提前对业务接口中的注解进行验证转换的标志位  
  final boolean validateEagerly;

  Retrofit(
      okhttp3.Call.Factory callFactory,
      HttpUrl baseUrl,
      List<Converter.Factory> converterFactories,
      List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor,
      boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
  ...	
}

看下Retrofit.Builder

  public static final class Builder {
    ... 
        
    Builder(Platform platform) {
      this.platform = platform;
    }
      
    public Builder() {
      this(Platform.get());
    }
    ... 
        
    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;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }        
  }

Builder构造方法:

  • 需要有一个Platform参数,表示当前的平台,这里当然是Android平台。

build方法:

  • baseUrl必须指定,否则抛异常。

  • 如果没有指定callFactory,则默认为OkHttpClient;如果需要对OkHttpClient进行详细的设置,就需要自己构建并传入OkHttpClient对象。

  • 如果没有指定callbackExecutor,就获取platformAndroid平台)的defaultCallbackExecutor,最终获取到的是一个MainThreadExecutor,它里面有一个主线程的Handler,调用MainThreadExecutorexecute就可以使用Handler向主线程post一个任务。

  • 接着会构建callAdapterFactories,其中的CallAdapter.Factory主要用于对retrofit.Call对象进行转化,其中的优先级顺序为:

    • 外界传入的callAdapterFactories
    • platform.defaultCallAdapterFactories(…)

    后面介绍CallAdapter的时候会再进行一些讲解

  • 接着构建converterFactories,其中的Converter.Factory主要用于转化数据,例如将返回的ResponseBody转化为对象等。其中的优先级顺序:

    • BuiltInConverters
    • 外界传入的converterFactories
    • platform.defaultConverterFactories()

    后面介绍Converter的时候会再进行一些讲解

接口实例的创建

我们在使用Retrofit进行网络请求的时候,需要先定义一个接口,然后调用retrofit.create(serviceClass)生成接口的一个实例,例如在「基本使用」的例子里,就是通过这种方式生成了一个IUser实例,那么这是如何做到的呢?答案是动态代理

动态代理的例子

我们先通过一个例子,简单地了解一下动态代理:

我们先定义一个注解

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class TIP(val value : String = "")

在定义一个接口

interface IMath {
    @TIP("加法运算")
    fun add(num1 : Int,num2 : Int) : Int    
}

动态代理的实现:

val proxyBn: Button = findViewById(R.id.proxy_test)
proxyBn.setOnClickListener {
    val iMath: IMath = Proxy.newProxyInstance(
        IMath::class.java.classLoader,
        arrayOf(IMath::class.java),
        object : InvocationHandler {
            override fun invoke(proxy: Any?, method: Method, args: Array<out Any>): Any {
                val num1: Int = args[0] as Int
                val num2: Int = args[1] as Int
                Log.d(TAG, "方法名字: ${method.name}")
                Log.d(TAG, "方法参数: num1为$num1,num2为$num2")

                val tip: TIP? = method.getAnnotation(TIP::class.java)
                tip?.let {
                    Log.d(TAG, "注解的值: ${it.value}")
                }
                return num1 + num2
            }
        }) as IMath

    Log.d(TAG, "调用结果: ${iMath.add(2, 3)}")
}

打印的输出信息为:

D/MainActivity: 方法名字: add
D/MainActivity: 方法参数: num1为2,num2为3
D/MainActivity: 注解的值: 加法运算
D/MainActivity: 调用结果: 5

我们调用实例iMath的方法,实际会调用到InvocationHandlerinvoke方法,在该方法可以拿到方法名字、参数、注解等,从而实现代理的功能。

Retrofit::create

Retrofit::create方法如下:

  public <T> T create(final Class<T> service) {
    // 对 Service 的接口进行检测
    validateServiceInterface(service);
    // 创建了网络请求接口的动态代理对象,即通过动态代理创建网络请求接口的实例并返回
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              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.
                // 如果调用的方法是Object类中的,则正常调用Object类中的方法  
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                // 方法参数  
                args = args != null ? args : emptyArgs;
                // 如果method是java8接口的default方法,则直接执行。否则会通过loadServiceMethod  
                // 方法获取一个ServiceMethod对象,然后调用它的invoke方法。 
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

该方法主要做了两件事情:

  1. 调用validateServiceInterface方法对 Service 的接口进行检测。
  2. 创建并返回一个代理对象。在InvocationHandlerinvoke方法里面,调用了loadServiceMethod方法获取一个ServiceMethod对象,一个ServiceMethod对象就代表网络请求接口里的一个方法,例如它可以代表我们IUser里的getUser请求方法,获取到ServiceMethod后,就调用它的invoke方法进行网络请求。

Retrofit::validateServiceInterface

  private void validateServiceInterface(Class<?> service) {
    // 若service不是接口,则抛出异常  
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }

    // 判断service接口及其继承的所有接口是否包含了泛型参数,若包含则抛出异常
    // 例如这样的接口会抛出异常:interface IUser<T,E> {...}  
    Deque<Class<?>> check = new ArrayDeque<>(1);
    // 将service添加到双端队列中  
    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());
      }
      // 将candidate继承的接口全添加到双端队列中  
      Collections.addAll(check, candidate.getInterfaces());
    }

    // 是否急切地对Service接口的方法进行处理,该值默认为false,可以在Retrofit.Builder中设置  
    if (validateEagerly) {
      Platform platform = Platform.get();
      for (Method method : service.getDeclaredMethods()) {
        // method不是default方法,并且不是static修饰的,则使用loadServiceMethod加载该方法  
        if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
          loadServiceMethod(method);
        }
      }
    }
  }

该方法会对service进行检测,主要做了下面几件事情:

  1. 若service不是接口,则抛出异常
  2. 判断service接口及其继承的所有接口是否包含了泛型参数,若包含则抛出异常
  3. 若validateEagerly为true,则提前对service声明的所有方法提前进行检测,也就是对service每个声明的方法都调用loadServiceMethod方法进行加载,loadServiceMethod会加载出ServiceMethod并进行缓存(缓存的目的是为了复用),调用loadServiceMethod加载方法的时候,因为使用了反射所以会有一定的性能损耗一般情况下是业务层调用到接口的某个方法(第一次调用该方法),才会使用loadServiceMethod进行相应的ServiceMethod的加载,这样的加载在时间上相对分散,因此此时的性能损耗不会很明显。而validateEagerly为true时对ServiceMethod的集中加载,性能损耗会比较明显,但是这样就可以尽早地检测开发者写的接口方法是否有问题,写的有问题会报错,这样可以尽早发现存在的问题,因此「validateEagerly为true」更多的是用在测试的时候

代理对象的执行

获取ServiceMethod

我们查看Retrofit::loadServiceMethod

  ServiceMethod<?> loadServiceMethod(Method method) {
    // 判断是否有method对应的ServiceMethod对象,有则直接返回  
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    // 利用serviceMethodCache加锁同步  
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      // 创建一个ServiceMethod对象并将其加入缓存中  
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    // 返回ServiceMethod对象  
    return result;
  }

serviceMethodCache是一个ConcurrentHashMap实例,ConcurrentHashMap是线程安全的HashMap。这里先从serviceMethodCache查看method是否有对应的ServiceMethod,有则直接返回,没有则调用ServiceMethod.parseAnnotations方法对method的注解进行处理,并将得到的ServiceMethod对象加入到ServiceMethodCache里面。

我们从中看出了Retrofit的缓存思想:serviceMethodCache是一个缓存,我们在调用Retrofit::create方法的时候传入的是一个class对象,而class对象在进程内是单例的,所以获取到它的同一个Method也是单例的,这里将Method作为ConcurrentHashMapKey,从而实现了对ServiceMethod的缓存与复用

ServiceMethod的构建

我们查看ServiceMethod类的定义:

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, 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);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}

ServiceMethodparseAnnotations方法就为我们构建了一个ServiceMethod,主要分为下面两步:

  1. 调用RequestFactory.parseAnnotations方法创建RequestFactory,这里主要是获取注解信息并且解析注解
  2. 调用HttpServiceMethod.parseAnnotations方法(传入前面获取的requestFactory),继续进行注解的解析,最终获取并返回一个HttpServiceMethod对象。

创建RequestFactory

获取注解信息

RequestFactory::parseAnnotations是一个静态方法

  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

这是一个建造者模式。它将method传入RequestFactory.Builder,再调用Builderbuild方法创建了一个RequestFactory对象。

查看RequestFactory::Builder的构造方法:

    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      // 方法注解  
      this.methodAnnotations = method.getAnnotations();
      // 方法参数类型(带泛型)  
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

Builder中通过反射获取了方法的注解、方法参数类型(带泛型)、方法参数的注解。

小插曲:一些实验

Method::getParameterTypesMethod::getGenericParameterTypes有什么区别?这里我做了个实验,对于下面的这个类

public class Test {
    public Long test(List<String> strs, List<Integer> nums,float num) {
        return 0L;
    }
	...
}

如果我们使用getParameterTypes方法:

Test test = new Test();
Class<?> testClass = test.getClass();
Method testMethod = testClass.getMethod("test", List.class, List.class, float.class);
System.out.println(testMethod.getName());
System.out.println(Arrays.toString(testMethod.getParameterTypes()));

输出如下:

test
[interface java.util.List, interface java.util.List, float]

如果我们使用getGenericParameterTypes方法:

Test test = new Test();
Class<?> testClass = test.getClass();
Method testMethod = testClass.getMethod("test", List.class, List.class,float.class);
System.out.println(testMethod.getName());
System.out.println(Arrays.toString(testMethod.getGenericParameterTypes()));

输出如下:

test
[java.util.List<java.lang.String>, java.util.List<java.lang.Integer>, float]

可以看出它们的区别是getGenericParameterTypes获取方法参数类型的时候会带上泛型,而getParameterTypes不会带上泛型。

另外,Method::getParameterAnnotations也有需要注意的点,我们先定义两个注解

@Retention(RetentionPolicy.RUNTIME)
public @interface Anno1 {
}

@Retention(RetentionPolicy.RUNTIME)
public @interface Anno2 {
}

然后将Test::test的方法参数使用注解修饰

public class Test {
    public Long test(@Anno1 @Anno2 List<String> strs, @Anno2 List<Integer> nums, 
                     float num) {
        return 0L;
    }
}

通过getParameterAnnotations方法去获取test方法参数的注解

Test test = new Test();
Class<?> testClass = test.getClass();
Method testMethod = testClass.getMethod("test", List.class, List.class, float.class);
System.out.println(testMethod.getName());
Annotation[][] paramAnnotations = testMethod.getParameterAnnotations();
for (Annotation[] paramAnnotation : paramAnnotations) {
    for (Annotation annotation : paramAnnotation) {
        System.out.print(annotation.toString() + " ");
    }
    System.out.println();
}    

输出信息:

test
@Anno1() @Anno2() 
@Anno2() 

注意,这里之所以可以获取到Anno1Anno2,是因为这两个注解的存活期到RetentionPolicy.RUNTIME,如果Anno1Anno2的存活期到RetentionPolicy.CLASSRetentionPolicy.SOURCE,那么在这里将获取不到Anno1Anno2注解,因为反射是在运行期执行的。

另外,paramAnnotations是二维数组,方法有多少个参数,二维数组的大小就是多少,其中的每个一维数组分别对应着每个参数上的注解

注解解析

再查看RequestFactory.Builderbuild方法

    RequestFactory build() {
      // 遍历方法的注解,对每个注解进行解析  
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      ...// 一些异常处理  

      // 方法参数的个数  
      int parameterCount = parameterAnnotationsArray.length;
      // 每个参数都创建一个ParameterHandler 
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }

      ...// 一些异常处理  
	    
      return new RequestFactory(this);
    }

build方法做了三件事情:

  1. 方法的每个注解调用parseMethodAnnotation方法进行解析
  2. 方法的每个参数调用了parseParameter解析,生成ParameterHandler对象
  3. 根据Builder创建并返回RequestFactory对象
方法注解的解析

RequestFactory.Builder::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);
      } 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(method, "@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } else if (annotation instanceof Multipart) {
        if (isFormEncoded) {
          throw methodError(method, "Only one encoding annotation is allowed.");
        }
        isMultipart = true;
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError(method, "Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
    }

这里对方法注解的处理方式主要可以分为三类:

  1. GETPOST等请求方法:调用RequestFactory.Builder::parseHttpMethodAndPath方法进行处理
  2. Headers的注解:调用RequestFactory.Builder::parseHeaders方法进行处理
  3. MultipartFormUrlEncoded注解:主要是在标记变量中进行记录

我们看下第12步是如何处理的。

GETPOST等请求方法的注解解析,使用RequestFactory.Builder::parseHttpMethodAndPath

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
    // 1.若已设置过httpMethod,则抛出异常
    if (this.httpMethod != null) {
        throw methodError(
            method,
            "Only one HTTP method is allowed. Found: %s and %s.",
            this.httpMethod,
            httpMethod);
    }
    // 记录 请求方法 及 是否有请求体
    this.httpMethod = httpMethod;
    this.hasBody = hasBody;

    // 若请求方法的注解(如GET)里面没有写值,则结束
    if (value.isEmpty()) {
        return;
    }

    // Get the relative URL path and existing query string, if present.
    // 2.判断请求方法的注解中的值是否合理,不合理则抛出异常
    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);
        }
    }

    // 3.记录相对Url;解析并记录注解中的占位符(parsePathParameters方法内部使用了正则表达式)
    this.relativeUrl = value;
    this.relativeUrlParamNames = parsePathParameters(value);
}

该方法主要做了下面的几件事情:

  1. 记录 请求方法 及 是否有请求体
  2. 判断请求方法的注解中的值是否合理,不合理则抛出异常
  3. 记录相对Url,解析并记录注解中的占位符

我们以GET请求方法注解为例,第2步主要是防止GET的出现类似"users?sortby={sortby}"这种值,它希望我们动态设置的参数使用@Query注解来实现,举一个例子:

    @GET("/banner")
    fun getBanners(@Query("type") type: Int): Call<BannerJson>

而不是

    @GET("/banner?type={type}")
    fun getBanners(@Path("type") type: Int): Call<BannerJson>

3步,例如我们的请求方法为

interface IUser {
    @GET("/users/{nickname}")
    fun getUser(@Path("nickname") nickname: String): Call<User>
}

那么计算后的值为

// 相对url
this.relativeUrl = "/users/{nickname}" 
// 也就是{}包裹的值,如果有多个{},那么Set<String>会有多个值
this.relativeUrlParamNames = 包含"nickname"的Set<String> 

Headers注解的解析,使用RequestFactory.Builder::parseHeaders方法:

    private Headers parseHeaders(String[] headers) {
      // 这是okhttp3的Headers.Builder  
      Headers.Builder builder = new Headers.Builder();
      // 遍历传入的headers
      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);
        }
        // 获取Header名和Header值  
        String headerName = header.substring(0, colon);
        String headerValue = header.substring(colon + 1).trim();
        // 如果Header是"Content-Type",则会进行一些特殊处理
        if ("Content-Type".equalsIgnoreCase(headerName)) {
          try {
            contentType = MediaType.get(headerValue);
          } catch (IllegalArgumentException e) {
            throw methodError(method, e, "Malformed content type: %s", headerValue);
          }
        } else {
          // 将Header添加到builder中  
          builder.add(headerName, headerValue);
        }
      }
      // 返回okhttp3.Headers  
      return builder.build();
    }

该方法主要做的事情:将传入的字符串数组headers,构造为okhttp3.Headers并返回,对于Content-Type类型的Header,会进行一些特殊的处理。

对方法参数的处理

RequestFactory.Builder::parseParameter

    # p:方法参数的位置
    # parameterType:方法参数的类型(带泛型)
    # annotations:方法参数的注解
    # allowContinuation:是否允许为Continuation(通过是否为最后一个参数进行判断)    
	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;
          }

          // 一个方法参数最多只能有一个Retrofit注解,多了则抛异常  
          if (result != null) {
            throw parameterError(
                method, p, "Multiple Retrofit annotations found, only one allowed.");
          }
		  // 记录结果
          result = annotationAction;
        }
      }

      if (result == null) {
        // 对kotlin协程方面的特殊处理  
        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;
    }

该方法主要做的事情:

  1. 使用parseParameterAnnotation解析方法参数的注解,且一个方法参数最多只能有一个Retrofit注解。最终返回result
  2. 若参数是方法的最后一个参数且为Continuation类型,说明与kotlin协程有关,做特殊处理。最终返回null

parseParameterAnnotation方法会对参数每种类型的注解进行特有的处理,然后返回相应的ParameterHandler

ServiceMethod 的创建

ServiceMethod 的创建使用HttpServiceMethod.parseAnnotations方法:

  // 检查接口方法的注释,以构造一个使用HTTP的可重用的ServiceMethod。这可能需要代价高昂的反射,所以
  // 对于要使用到的ServiceMethod最好只构建一次然后重用它
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    // 记录是否为suspend函数  
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;
	// 获取方法注解
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        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 {
      // 记录方法的返回类型(含泛型信息),如Call<User>  
      adapterType = method.getGenericReturnType();
    }

    // 创建CallAdapter对象  
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
     // 接口方法的实际返回类型,例如Call<User>会返回User   
    Type responseType = callAdapter.responseType();
   
    ...(一些异常处理)
	// 创建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<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);
    }
  }

这里暂时先不考虑Retrofit对协程的支持。这个方法主要做了下面几件事:

  1. 记录方法的返回类型(含泛型信息),如Call<User>
  2. 创建CallAdapter对象
  3. 创建Converter对象
  4. 创建并返回一个CallAdapted对象,CallAdapted继承至HttpServiceMethod
CallAdapter

CallAdapter用于将retrofit2.Call<R>对象适配为类型为T的对象,定义如下:

// CallAdapter实例由CallAdapter.Factory创建,Retrofit里面有CallAdapter.Factory的实例
public interface CallAdapter<R, T> {
  // 返回Response Type,如Call<User>的Response Type就是User  
  Type responseType();
  // 适配:Call<R> -> T  
  T adapt(Call<R> call);
    
  // 基于接口方法的返回类型,创建CallAdapter实例  
  abstract class Factory {
    // 如果该工厂可以处理指定的returnType和annotations的接口方法,则返回CallAdapter,否则返回null
    // returnType:接口方法的返回类型,如Call<User>  
    public abstract @Nullable CallAdapter<?, ?> get(
        Type returnType, Annotation[] annotations, Retrofit retrofit);      
      
    // 提取泛型参数的上界,例如index = 1,type = Map<String, ? extends Runnable>,则
    // 返回值为Runnable 
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }
     
    // 返回Type的raw class type,例如type = List<? extends Runnable>,则返回List.class  
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }      
  }
}

查看HttpServiceMethod::createCallAdapter方法,看CallAdapter是如何被创建的:

  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

  // 从可用的factories中返回returnType相应的CallAdapter
  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

Retrofit::nextCallAdapter

  # skipPast:null
  # returnType:接口方法的返回类型,如Call<User>
  # annotations:接口方法的注解    
  public CallAdapter<?, ?> nextCallAdapter(
      @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
    Objects.requireNonNull(returnType, "returnType == null");
    Objects.requireNonNull(annotations, "annotations == null");
	
    // 从列表开始寻找的位置,这里是从0开始 
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      // 若索引处的CallAdapter.Factory可以处理该接口方法,则返回CallAdapter,否则返回null  
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      // 可以获取到CallAdapter则返回它
      if (adapter != null) {
        return adapter;
      }
    }

    // 没有获取到适合该接口方法的CallAdapter,则拼接异常信息并抛出异常 
    StringBuilder builder = ...
    ...
    throw new IllegalArgumentException(builder.toString());
  }

该方法会遍历RetrofitcallAdapterFactories,查看是否有可以处理指定的returnTypeannotationsCallAdapter.Factory,有则返回该CallAdapter,整个列表都没有找到合适的CallAdapter.Factory,则抛出异常。

回到Retrofit.Builder::build方法,可以知道callAdapterFactories中有哪些元素

List<CallAdapter.Factory> callAdapterFactories = 
    					new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

PlatformdefaultCallAdapterFactories如下:

  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }

在「Retrofit对象创建」当中提到,Platform的实例是AndroidAndroid实例通过SDK版本是否大于等于24来判断hasJava8Types的值是否为true,我们这里认为它是true。因为hasJava8Types的值为true,所以在defaultCallAdapterFactories方法会将CompletableFutureCallAdapterFactoryDefaultCallAdapterFactory添加到callAdapterFactories中,所以callAdapterFactories的元素:

  1. 用户自定义的CallAdapter.Factory(我们一般不会自定义CallAdapter.Factory)
  2. CompletableFutureCallAdapterFactory(只处理接口方法的返回类型为CompletableFuture<T>的)
  3. DefaultCallAdapterFactory

RxJava的适配器:XXX.addCallAdapterFactory(RxJava3CallAdapterFactory.create()),就是属于一种「用户自定义的CallAdapter.Factory」。

并且由上至下优先级递减,其中DefaultCallAdapterFactory的优先级最低。一般情况下,由DefaultCallAdapterFactory处理我们的请求,这里直接分析它即可:

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  // 默认情况下,这是一个MainThreadExecutor,可以通过handler将任务调度到主线程中执行  
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  # returnType:接口方法的返回类型,如Call<User>
  # annotations:接口方法的注解
  @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<Foo> or Call<? extends Foo>");
    }
    // 获取返回类型的泛型参数的上界  
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    // 判断方法注解是否包含SkipCallbackExecutor.class,一般不包含,所以这里executor的值为
    // callbackExecutor(默认情况下,它是一个MainThreadExecutor)  
    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;

    // 创建并返回CallAdapter  
    return new CallAdapter<Object, Call<?>>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      // 将Call<Object>适配为Call<Object>  
      @Override
      public Call<Object> adapt(Call<Object> call) {
        // 正常情况下executor不为null,因此call会被适配为一个ExecutorCallbackCall  
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }
  
  static final class ExecutorCallbackCall<T> implements Call<T> {...}    
}

简单来说,DefaultCallAdapterFactoryget方法会返回一个CallAdapter,通过CallAdapteradapt方法可以将传入的retrofit2.Call适配包装为一个ExecutorCallbackCall

这个ExecutorCallbackCall实际上就是我们业务层拿到的retrofit2.Call,可以调用它的enqueue或者execute方法进行网络请求,ExecutorCallbackCallDefaultCallAdapterFactory的静态内部类,其定义如下:

  static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    // retrofit2.Call  
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    # callback:业务层传入的Callback  
    @Override
    public void enqueue(final Callback<T> callback) {
      Objects.requireNonNull(callback, "callback == null");

      // 调用delegate的enqueue进行请求  
      delegate.enqueue(
          new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> 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<T> call, final Throwable t) {
               // 将回调给业务层的代码,切到主线程中执行  
              callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }
    ...
    @Override
    public Response<T> execute() throws IOException {
      return delegate.execute();
    }
	...
  }

两种执行方式:

  • enqueue:异步执行。使用callbackExecutor将给业务层的回调代码切换到主线程中执行。
  • execute:同步执行。

实际上,callbackExecutor也不一定是切换到主线程的MainThreadExecutor,但是默认情况下是MainThreadExecutor,这里我们就认为它是MainThreadExecutor,展开讨论。

ExecutorCallbackCall声明的其余方法不多介绍:

image-20220111125105998

那么,传入ExecutorCallbackCalldelegate变量是怎样的呢?后面将会介绍。

后面我们会知道delegate变量其实是一个OkHttpCall实例。

Converter

Converter是一个接口,用于将类型为F的数据转换为类型T

// Converter实例由Converter.Factory创建,Retrofit里面有Converter.Factory的实例
public interface Converter<F, T> {
  @Nullable
  T convert(F value) throws IOException;

  abstract class Factory {
    // 该Factory可以处理type和annotations的接口方法,则返回Converter,否则返回null  
    # type:接口方法的实际返回类型,例如接口方法声明的是Call<User>类型,则这里传入的是User类型   
    # annotations:接口方法的注解    
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
        Type type, Annotation[] annotations, Retrofit retrofit) {
      return null;
    }

    public @Nullable Converter<?, RequestBody> requestBodyConverter(
        Type type,
        Annotation[] parameterAnnotations,
        Annotation[] methodAnnotations,
        Retrofit retrofit) {
      return null;
    }

    public @Nullable Converter<?, String> stringConverter(
        Type type, Annotation[] annotations, Retrofit retrofit) {
      return null;
    }

    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }   
}

Converter.Factory的几个方法:

  • responseBodyConverter:完成ResponseBody到实际的返回类型的转化,实际返回类型例如是Call<User>里面的泛型User
  • requestBodyConverter:完成对象到RequestBody的构造。

关于Converter.Factory更多信息,可以查看 Retrofit2 完全解析 探索与okhttp之间的关系_Hongyang-CSDN博客 的 「六、自定义Converter.Factory」 一节。

查看HttpServiceMethod::createResponseConverter如何创建Converter

  private static <ResponseT> 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 <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }

Retrofit::nextResponseBodyConverter

  public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    Objects.requireNonNull(type, "type == null");
    Objects.requireNonNull(annotations, "annotations == null");

    // 从列表开始寻找的位置,这里是从0开始  
    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      // 若索引处的Converter.Factory可以处理接口方法,则返回Converter,否则返回null 
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      // 可以获取到Converter则返回它  
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }

    // 没有获取到适合该接口方法的Converter,则拼接异常信息并抛出异常 
    StringBuilder builder = ...
    ...
    throw new IllegalArgumentException(builder.toString());
  }

获取Converter和获取CallAdapter的过程非常类似。

Retrofit.Builder::build得知,列表中会有三种类型的Converter.Factory

  • BuiltInConverters
  • 用户自定义的Converter.Factory,如GsonConverterFactory
  • platform.defaultConverterFactories,其实就是OptionalConverterFactory

BuiltInConverters:当接口方法声明的是Call<ResponseBody>Call<Void>Call<Unit>的时候,BuiltInConverters可以处理,并返回相应的Converter

OptionalConverterFactory:从该类的responseBodyConverter方法可以看出,该类与Optional类有关,若我们的接口方法的返回值没有用到Optional类,则OptionalConverterFactory会返回null

另外要说明的是,BuiltInConverters是优先级最高的Converter.Factory,这防止其它工厂覆盖它的行为;而OptionalConverterFactory的优先级比自定义工厂的优先级低,是优先级最低的Converter.Factory

CallAdapted

在不考虑Retrofit协程支持的情况下,HttpServiceMethod::parseAnnotations最终会创建并返回一个CallAdapted对象,CallAdapted的继承关系:

CallAdapted -> HttpServiceMethod -> ServiceMethod

CallAdaptedHttpServiceMethod的静态内部类

ServiceMethod是一个抽象类,定义如下:

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {...}
  // 抽象方法invoke  
  abstract @Nullable T invoke(Object[] args); 
}

它内部定义了抽象方法invoke,在Retrofit::create动态代理InvocationHandler中,就调用了ServiceMethodinvoke方法。

ServiceMethod的直接子类只有一个,即HttpServiceMethod,它也是一个抽象类:

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
	...
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
    
  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);    
    
  static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {...}  
  ...  
}

HttpServiceMethod的大部分方法前面都已经看过了(即省略号的部分)。上面列出的代码,主要关注的点:

  1. invoke方法中,创建了一个retrofit2.OkHttpCall对象,并且调用虚方法adaptOkHttpCall进行转化,adapt方法在子类中实现。
  2. CallAdapted继承至HttpServiceMethod

注意,HttpServiceMethod重写了父类的invoke方法并标记为final,意味着子类无法重写该方法,又由于ServiceMethod的直接子类只有HttpServiceMethod一个,所以调用ServiceMethod::invoke,实际上调用的是HttpServiceMethod::invoke

CallAdapted定义如下:

  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<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);
    }
  }

HttpServiceMethod::parseAnnotations中创建CallAdapted对象的语句是:

return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);

CallAdapted类中存在很多泛型参数,这里在一个假定的场景下进行讨论,方便理解,假如接口方法的返回类型是Call<User>,并且使用的CallAdapter.FactoryDefaultCallAdapterFactory,则CallAdapted类中的泛型参数为:

ResponseT = Object;
ReturnT = Call<User>;
即CallAdapted<Object, Call<User>>

因此,CallAdaptedadapt方法就可以实现转化:retrofit2.Call -> retrofit2.Call。

关系梳理

我们业务代码中通过retrofit.create可以拿到一个接口如IUser,该接口是一个代理对象,调用IUser::getUser方法希望获取一个retrofit2.Call<User>,实际会调用到代理对象InvocationHandlerinvoke方法中,接着会调用loadServiceMethod(method).invoke(args),在不考虑缓存命中的情况下,loadServiceMethod(method)会获取到一个CallAdapted对象,接着调用CallAdaptedinvoke方法,实际会执行父类HttpServiceMethod::invoke,里面会创建一个retrofit2.OkHttpCall<Object>对象,然后调用子类CallAdaptedadapt方法,将该OkHttpCall转化为retrofit2.Call<User>

CallAdapted::adapt内部依靠CallAdapter::adapt完成对象转化,该CallAdapter来源于DefaultCallAdapterFactory::get,返回的CallAdapter如下:

    return new CallAdapter<Object, Call<?>>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call<Object> adapt(Call<Object> call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };

所以,CallAdapted::adapt内部的转化实际是:retrofit2.OkHttpCall<Object> -> ExecutorCallbackCall<User>。所以,业务层调用IUser::getUser方法拿到的实际是ExecutorCallbackCall<User>ExecutorCallbackCall继承至retrofit2.Call)。

前面介绍过,ExecutorCallbackCall内部有一个类型为retrofit2.Call<User>delegate代理,在异步请求方法enqueue中,会调用delegate.enqueue进行网络请求,然后将给业务层的回调切到主线程中执行;在同步请求方法execute中,就是直接调用delegate代理的execute方法。而这个delegate代理实际上就是在HttpServiceMethod::invoke创建的retrofit2.OkHttpCall对象。

一个简单的关系图:

image-20220113103830515

retrofit2.Call

该接口定义了下面的方法:

public interface Call<T> extends Cloneable {
  // 同步请求  
  Response<T> execute() throws IOException;
  // 异步请求  
  void enqueue(Callback<T> callback);
  boolean isExecuted();
  void cancel();
  boolean isCanceled();
  Call<T> clone();
  Request request();
  Timeout timeout();
}

OkHttpCall

retrofit2.OkHttpCall实现了retrofit2.Call接口。

当业务层调用拿到的retrofit2.Call(即ExecutorCallbackCall)的enqueue或者execute方法时,都会调用到retrofit2.OkHttpCallenqueue或者execute方法。

enqueue

  @Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      // 检测该OkHttpCall是否已经执行过,若执行过则抛出异常。  
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          // 创建一个okhttp3.Call对象。
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    // 检测是否被取消。  
    if (canceled) {
      call.cancel();
    }

    // 使用okhttp3.Call发起异步的okhttp网络请求  
    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
              // 解析响应  
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }

            try {
              // 回调响应  
              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(e);
          }

          private void callFailure(Throwable e) {
            try {
              // 回调,通知失败  
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
  }

代码很长,逻辑很简单。该方法主要做了下面几件事情:

  1. 检测该OkHttpCall是否已经执行过,若执行过则抛出异常。
  2. 调用createRawCall方法创建一个okhttp3.Call对象。
  3. 检测是否被取消。
  4. 使用okhttp3.Call发起okhttp的网络请求,并传入okhttp3.Callback回调,这里就是真正进行网络请求的地方
    • 请求成功:通过parseResponse方法解析响应,调用callback.onResponse方法进行回调,该callback由ExecutorCallbackCall::enqueue传入。
    • 请求失败:调用callback.onFailure回调方法通知失败,该callback由ExecutorCallbackCall::enqueue传入。

execute

  @Override
  public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      // 检测该OkHttpCall是否已经执行过,若执行过则抛出异常。 
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
	  // 获取一个okhttp3.Call对象
      call = getRawCall();
    }

    // 检测是否被取消  
    if (canceled) {
      call.cancel();
    }

    // 使用okhttp3.Call发起同步的okhttp网络请求,并使用parseResponse方法解析响应  
    return parseResponse(call.execute());
  }

该方法的逻辑也很简单:

  1. 检测该OkHttpCall是否已经执行过,若执行过则抛出异常。
  2. 获取一个okhttp3.Call对象。
  3. 检测是否被取消。
  4. 使用okhttp3.Call发起同步的okhttp网络请求,并使用parseResponse方法解析响应。

个人有一点疑问:

既然OkHttpCall通过executed变量防止重复进行网络请求,那么对rawCall还要这么多判断干啥呢?这个getRawCall方法是不是有点多余?不可以直接使用createRawCall方法去创建一个okhttp3.Call对象吗?

okhttp3.Call 的 获取/创建

OkHttpCallenqueue方法,使用createRawCall创建一个okhttp3.Call对象;OkHttpCallexecute方法使用getRawCall 获取/创建 一个okhttp3.Call对象。

OkHttpCall::getRawCall

  private okhttp3.Call getRawCall() throws IOException {
    // 若之前已经创建了okhttp3.Call对象,则直接返回该对象
    okhttp3.Call call = rawCall;
    if (call != null) return call;

    // Re-throw previous failures if this isn't the first attempt.
    // 若这不是第一次创建okhttp3.Call,并且之前创建的时候抛出异常,则这里重抛异常  
    if (creationFailure != null) {
      if (creationFailure instanceof IOException) {
        throw (IOException) creationFailure;
      } else if (creationFailure instanceof RuntimeException) {
        throw (RuntimeException) creationFailure;
      } else {
        throw (Error) creationFailure;
      }
    }

    // Create and remember either the success or the failure.
    // 创建okhttp3.Call对象,若有异常则记录  
    try {
      return rawCall = createRawCall();
    } catch (RuntimeException | Error | IOException e) {
      throwIfFatal(e); // Do not assign a fatal error to creationFailure.
      creationFailure = e;
      throw e;
    }
  }

可以看出,最终还是要调用createRawCall方法创建一个okhttp3.Call对象,OkHttpCall::createRawCall方法:

  private okhttp3.Call createRawCall() throws IOException {
    // 创建okhttp3.Call对象  
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    // 返回call对象  
    return call;
  }

callFactory的类型是okhttp3.Call.Factory,来源于Retrofit的成员变量,在Retrofit.Builder的配置中,若开发者没有指定callFactory,那么它默认是OkHttpClient()requestFactory是在前面的ServiceMethod::parseAnnotations中,通过RequestFactory.parseAnnotations创建的,在创建的时候会对接口方法的相关信息进行解析,所以requestFactory代表了接口方法的信息,它的create方法可以创建一个okhttp3.Request对象,便于我们使用okhttp发起网络请求。

所以在createRawCall方法中,默认是通过OkHttpClientnewCall方法创建一个okhttp3.Call对象并返回。

parseResponse

parseResponse用于将okhttp响应转化为retrofit2响应。假如我们的接口方法返回值为Call<User>,那么parseResponse职责就是将okhttp3.Response转化为retrofit2.Response<User>

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.
    // 替换原来响应中的ResponseBody   
    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);
    }

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      // 使用responseConverter.convert进行数据类型的转换  
      T body = responseConverter.convert(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;
    }
  }

该方法的主要逻辑是使用responseConverter.convert进行数据类型的转换,然后创建并返回retrofit2.Response对象。其中responseConverter的类型是Converter(比如它可以是GsonResponseBodyConverter),它是由RetrofitConverter.Factory创建的,创建过程在前面的「Converter」一节中已经介绍过了。

对协程的支持

Retrofit2.6版本开始对协程进行支持。

例子如下:

interface IUser {
    @GET("/users/{nickname}")
    suspend fun getUser(@Path("nickname") nickname: String): User
}
val iUser = ServiceCreator.create(IUser::class.java)
GlobalScope.launch(Dispatchers.Main) {
    val user = iUser.getUser("giagor")
    Log.d(TAG, "成功: $user")
}

注意两点:

  1. 接口方法使用suspend修饰。
  2. 接口方法的返回值由Call<User>改成User
  3. 开发者只需要调用iUser.getUser就可以进行网络请求,而不需要调用enqueue、execute之类的方法。

接下来看下与协程支持相关的源码。

在「创建RequestFactory」里,会走到RequestFactory.Builderbuild方法:

    RequestFactory build() {
      ...
      // 方法参数的个数  
      int parameterCount = parameterAnnotationsArray.length;
      // 每个参数都创建一个ParameterHandler 
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }

      ...// 一些异常处理  
	    
      return new RequestFactory(this);
    }

在对方法的每个参数进行解析的时候,会走到RequestFactory.Builder::parseParameter方法:

    # p:方法参数的位置
    # parameterType:方法参数的类型(带泛型)
    # annotations:方法参数的注解
    # allowContinuation:是否允许为Continuation(通过是否为最后一个参数进行判断)    
	private @Nullable ParameterHandler<?> parseParameter(
        int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
      ParameterHandler<?> result = null;
      ...
      if (result == null) {
        // 对kotlin协程方面的特殊处理  
        if (allowContinuation) {
          try {
            // 如果方法最后一个参数为Continuation,就将isKotlinSuspendFunction标记位
            // 设置为true  
            if (Utils.getRawType(parameterType) == Continuation.class) {
              isKotlinSuspendFunction = true;
              return null;
            }
          } catch (NoClassDefFoundError ignored) {
          }
        }
        throw parameterError(method, p, "No Retrofit annotation found.");
      }

      return result;
    }

后面在「ServiceMethod的创建」里,会根据isKotlinSuspendFunction标记位进行些逻辑判断,并最终决定创建什么类型的ServiceMethod

  // 检查接口方法的注释,以构造一个使用HTTP的可重用的ServiceMethod。这可能需要代价高昂的反射,所以
  // 对于要使用到的ServiceMethod最好只构建一次然后重用它
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    // 记录是否为suspend函数  
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;
	// 获取方法注解
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    // 如果是Kotlin的suspend方法  
    if (isKotlinSuspendFunction) {
      // 获取方法参数类型(带泛型)
      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<T>.
        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 {
      ...
    }

    // 创建CallAdapter对象  
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
     // 接口方法的实际返回类型,例如Call<User>会返回User   
    Type responseType = callAdapter.responseType();
   
    ...(一些异常处理)
	// 创建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) {
      // 是suspend函数,且接口方法的返回值为Response,则创建一个SuspendForResponse对象  
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      // 是suspend函数,且接口方法的返回值不是Response,而是User之类的  
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }

该方法中,与协程相关的代码有以下几部分

  1. 如果接口方法是suspend方法,则获取 Continuation 的泛型参数,从而知道 suspend 方法的返回值类型。
  2. 如果suspend方法返回值为 Response,则将continuationWantsResponse标记位设置为true
  3. isKotlinSuspendFunctiontrue的前提下,根据 suspend 方法需要的是 Response 还是具体的类型,分别返回 SuspendForResponseSuspendForBody 对象。

SuspendForResponse

SuspendForResponse继承至HttpServiceMethod并且是它的一个静态内部类:

  static final class SuspendForResponse<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;

    SuspendForResponse(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, Call<ResponseT>> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override
    protected Object adapt(Call<ResponseT> call, Object[] args) {
      // 得到的call是ExecutorCallbackCall  
      call = callAdapter.adapt(call);

      // 获取接口方法的最后一个参数Continuation
      //noinspection unchecked Checked by reflection inside RequestFactory.
      Continuation<Response<ResponseT>> continuation =
          (Continuation<Response<ResponseT>>) args[args.length - 1];

      // 调用awaitResponse方法,注意call和continuation都作为参数传入  
      // See SuspendForBody for explanation about this try/catch.
      try {
        return KotlinExtensions.awaitResponse(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }

awaitResponse方法:

# 函数类型等价为:fun <T> awaitResponse(retrofit2.Call<T>,Continuation) : Response<T>
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>) {
        // 直接将Response返回给业务层  
        continuation.resume(response)
      }

      override fun onFailure(call: Call<T>, t: Throwable) {
        continuation.resumeWithException(t)
      }
    })
  }
}

可以看到,它使用suspendCancellableCoroutine主动挂起当前的协程,然后使用ExecutorCallbackCallenqueue进行网络请求,ExecutorCallbackCall内部又调用到OkHttpCallenqueue方法进行网络请求,最终会调用到okhttp3.Callenqueue进行真正的网络请求。

OkHttp进行异步的网络请求的时候,协程是挂起状态,等网络请求结束后会通过续体Continuation恢复协程,从而让协程中的代码可以继续往下执行。

SuspendForBody

SuspendForBody也是HttpServiceMethod的静态内部类并继承至它:

  static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
    private final boolean isNullable;

    SuspendForBody(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, Call<ResponseT>> callAdapter,
        boolean isNullable) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
      // 接口方法的返回值是否为「可空」的
      this.isNullable = isNullable;
    }

    @Override
    protected Object adapt(Call<ResponseT> call, Object[] args) {
      // 得到的call是ExecutorCallbackCall    
      call = callAdapter.adapt(call);

      // 获取接口方法的最后一个参数Continuation  
      //noinspection unchecked Checked by reflection inside RequestFactory.
      Continuation<ResponseT> continuation = (Continuation<ResponseT>) 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
      // declared on the interface method. To avoid the synchronous checked exception being wrapped
      // 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 {
        // 根据isNullable的值,调用相应的挂起函数  
        return isNullable
            ? KotlinExtensions.awaitNullable(call, continuation)
            : KotlinExtensions.await(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }

如果isNullabletrue,则调用awaitNullable方法:

@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?>) {
        // 对Response做一些处理后,再返回给业务层  
        if (response.isSuccessful) {
          continuation.resume(response.body())
        } else {
          continuation.resumeWithException(HttpException(response))
        }
      }

      override fun onFailure(call: Call<T?>, t: Throwable) {
        continuation.resumeWithException(t)
      }
    })
  }
}

可以看到,它的处理过程和前面提到的awaitResponse方法类似。唯一不同的地方在于awaitNullable方法中会对response做一些处理,通过判断response是否为isSuccessful,从而将body或者异常返回给业务层。

再看看await方法:

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 method = invocation.method()
            val e = KotlinNullPointerException("Response from " +
                method.declaringClass.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)
      }
    })
  }
}

它的处理过程和awaitNullable方法类型,唯一区别在于await方法中,还增加了一个response.body是否为null的判断,为null则返回异常给业务层,不为null则将body正常地返回给业务层。

总结

总的调用流程图(不含对协程支持的部分):

image-20220121114541843

请求方式:业务层通过iUser.getUser拿到retrofit2.Call<User>对象后

  • 同步请求:调用Call<User>::execute()
  • 异步请求:调用Call<User>::enqueue(...)

Retrofit代码中基本很少涉及到对网络请求的处理,它更多的是对OkHttp的封装,在 OkHttp 现有的 API 上提供了一套更便于使用的框架

Retrofit的注解是一种运行时注解,它通过动态代理对Service对象进行创建,通过反射对注解进行解析,这样虽然会有一定的性能损耗,但性能的损耗却带来了十分易用的 API。开发者的Service接口中,每个接口方法对应着一个ServiceMethod对象

另外,「运行时注解+反射」是一种常用的在运行时动态获取信息的手段。

Retrofit创建Service对象时使用了动态代理,在返回代理对象之前,会先对 Service 的接口进行检测,若开发者将validateEagerly设置为true,则会提前解析该Service接口中的所有方法,为这些方法创建对应的ServiceMethod对象,这种做法有利于尽早发现接口方法的书写错误,一般用于测试使用,将validateEagerly设置为true的缺点是,性能损耗表现得更集中、明显。默认validateEagerly的值为false,这样会在Service接口的方法调用时再创建对应的ServiceMethod对象。Retrofit通过serviceMethodCache对已经创建的ServiceMethod对象进行缓存,从而避免了重复解析带来的性能损耗

HttpServiceMethod.parseAnnotations 方法中会完成 ServiceMethod 对象的创建,它在创建的过程中同时进行了接口对应的 CallAdapter 以及 Converter 的创建。

其中,CallAdapter 用于将Call<R> 对象适配为需要的类型 T 对象,也就是Call 进行转换

Converter 则是用于将 F 类型的数据转换为 T,往往是用于对 Response 的 body 进行转换

对于 CallAdapterConverter 都是通过它们对应的工厂类进行创建,创建时会根据工厂列表的顺序从前向后尝试进行创建,也就是说在工厂列表中越靠前的工厂其优先级越大

Retrofit 的网络请求的执行依赖于 OkHttp,它首先会通过 RequestFactory 进行 okhttp3.Request 的构造,RequestFactory的信息由前面的注解解析中得来。之后会根据这个 Request 创建一个 okhttp3.Call对象,在同步和异步请求时分别调用其对应的 executeenqueue 方法

Retrofit2.6版本开始对协程进行支持,所谓对协程的支持,其实就是在进行网络异步请求的时候,将协程主动地进行挂起,等到异步请求完成后(请求成功或请求失败),这时再通过续体Continuation恢复协程,让协程的后续代码可以继续执行

参考

  1. Retrofit 源码解析:基于 OkHttp 的网络请求框架 - 掘金

  2. Retrofit2 完全解析 探索与okhttp之间的关系_Hongyang-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值