0%

Android 三方库源码解析系列(四):Retrofit 原理及源码解析

一. 前言

  • Retrofit: A type-safe HTTP client for Android and Java.

二. Demo

  • Demo

    • 引入 Retrofit

      1
      2
      3
      dependencies {
      implementation 'com.squareup.retrofit2:retrofit:2.9.0'
      }
    • 发起一个网络请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      interface ApiService {

      @GET("getUserData")
      fun getUserData(): Call<ResponseBody>

      }

      fun main() {
      val retrofit = Retrofit.Builder()
      .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
      .build()
      val service = retrofit.create(ApiService::class.java)
      val call: Call<ResponseBody> = service.getUserData()
      call.enqueue(object : Callback<ResponseBody> {
      override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
      val userBean = response.body()?.string()
      println("userBean: $userBean")
      }

      override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
      println("onFailure: $t")
      }
      })
      }
    • 输出结果

      1
      userBean: {"userName":"JBl","userAge":7816977017260632}
  • Retrofit 是建立在 OkHttp 之上的一个网络请求封装库,内部依靠 OkHttp 来完成实际的网络请求。Retrofit 在使用上很简洁,API 是通过 interface 来声明的,只需要通过 interface 来声明API 路径、请求方式、请求参数、返回值类型等各个配置项,然后调用方法就可以发起网络请求

  • 从上述例子可以看到,getUserData() 方法所代表的 API 的请求结果是一个 Json 格式的字符串,其返回值类型被定义为 Call<ResponseBody>,此处的 ResponseBodyokhttp3.ResponseBody,是 OkHttp 提供的对网络请求结果的包装类,Call 即retrofit2.Call,是 Retrofit 对 okhttp3.Call 做的一层包装,OkHttp 在实际发起请求的时候使用的回调是 okhttp3.Call,回调内部就会来中转调用 retrofit2.Call,以便将请求结果转交给外部

  1. converter-gson

    • 上述例子虽然简单,但还不够方便,因为既然 API 的返回值我们已知就是 Json 格式的了,那么我们自然就希望 getUserData() 方法的返回值直接就是一个 Bean 对象,而不是拿到一个 String 对象后还需要自己再去进行反序列化,这可以通过 converter-gson 这个库来达到这个效果

      1
      2
      3
      4
      dependencies {
      implementation 'com.squareup.retrofit2:retrofit:2.9.0'
      implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
      }
    • 修改代码,然后就可以直接在 Callback 中拿到 UserBean 对象了

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      interface ApiService {

      @GET("getUserData")
      fun getUserData(): Call<UserBean>

      }

      data class UserBean(val userName: String, val userAge: Long)

      fun main() {
      val retrofit = Retrofit.Builder()
      .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
      .addConverterFactory(GsonConverterFactory.create())
      .build()
      val service = retrofit.create(ApiService::class.java)
      val call: Call<UserBean> = service.getUserData()
      call.enqueue(object : Callback<UserBean> {
      override fun onResponse(call: Call<UserBean>, response: Response<UserBean>) {
      val userBean = response.body()
      println("userBean: $userBean")
      }

      override fun onFailure(call: Call<UserBean>, t: Throwable) {
      println("onFailure: $t")
      }
      })
      }
  2. adapter-rxjava2

    • 再然后,如果我们也看 Call<UserBean> 不爽,想要通过 RxJava 的方式来进行网络请求也是可以的,此时就需要再使用到 adapter-rxjava2 这个库了

      1
      2
      3
      4
      5
      dependencies {
      implementation 'com.squareup.retrofit2:retrofit:2.9.0'
      implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
      implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
      }
    • 修改代码,此时就完全不用使用到 Call.enqueue() 来显式发起网络请求了,当进行 subscribe() 的时候就会触发网络请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      interface ApiService {

      @GET("getUserData")
      fun getUserData(): Observable<UserBean>

      }

      data class UserBean(val userName: String, val userAge: Long)

      fun main() {
      val retrofit = Retrofit.Builder()
      .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
      .build()
      val service = retrofit.create(ApiService::class.java)
      val call: Observable<UserBean> = service.getUserData()
      call.subscribe(object : Consumer<UserBean> {
      override fun accept(userBean: UserBean?) {
      println("userBean: $userBean")
      }

      }, object : Consumer<Throwable> {
      override fun accept(t: Throwable?) {
      println("onFailure: $t")
      }
      })
      }
  3. 三个问题

    • 优点:Retrofit 在抽象程度上是很高的。不管是需要 Call 类还是 Observable 类型的包装类,只需要添加不同的 CallAdapterFactory 即可,就算想返回 LiveData 类型都是可以实现的。也不管是需要 ResponseBody 类型还是具体的 Bean 对象类型,也只需要添加不同的 ConverterFactory 即可,就算 API 的返回值是 XML 格式也可以进行映射解析
    • 问题
      1. 问题一:Retrofit 是如何将 interface 内部的方法转化为一个个实际的 GET、POST、DELETE 等各式各样的网络请求?例如,Retrofit 是如何将 getUserData() 转换为一个 OkHttp 的 GET 请求?
      2. 问题二: Retrofit 是如何将 API 的返回值映射为具体的 Bean 对象?例如,ResponseBody 是如何映射为 UserBean?
      3. 问题三:Retrofit 是如何抽象不同的 API 返回值包装类?例如,Call 是如何替换为 Observable ?

三. Retrofit.create()

  • Retrofit.create() 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public <T> T create(final Class<T> 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.
    if (method.getDeclaringClass() == Object.class) {
    //如果外部调用的是 Object 中声明的方法的话则直接调用
    //例如 toString()、hashCode() 等方法
    return method.invoke(this, args);
    }
    args = args != null ? args : emptyArgs;
    //根据 method 是否默认方法来决定如何调用
    return platform.isDefaultMethod(method)
    ? platform.invokeDefaultMethod(method, service, proxy, args)
    : loadServiceMethod(method).invoke(args);
    }
    });
    }
    • 这里的重点就是 Proxy.newProxyInstance 所实现的动态代理模式了。通过动态代理,Retrofit 会将我们对 ApiService 的调用操作转发给 InvocationHandler 来完成
    • Retrofit 在后续会通过反射拿到我们在声明 getUserData() 时标注的各个配置项,例如API 路径、请求方式、请求参数、返回值类型等各个信息,然后将这些配置项拼接为 OkHttp 的一个原始网络请求。当我们调用了 call.enqueue() 方法时,这个操作就会触发 InvocationHandler 去发起 OkHttp 网络请求了
  • Retrofit 会根据 method 是否是默认方法来决定如何调用,这里主要看 loadServiceMethod(method) 方法,该方法的主要逻辑是

    1. 将每个代表接口方法的 method 对象转换为 ServiceMethod 对象,该对象中就包含了 API 的具体信息

    2. 因为 API 可能先后会被调用多次,所以将构造出来的 ServiceMethod 对象缓存到 serviceMethodCache 中以实现复用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();  

      ServiceMethod<?> loadServiceMethod(Method method) {
      ServiceMethod<?> result = serviceMethodCache.get(method);
      if (result != null) return result;

      synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
      //重点
      result = ServiceMethod.parseAnnotations(this, method);
      serviceMethodCache.put(method, result);
      }
      }
      return result;
      }

四. ServiceMethod

  • 从上面可知,loadServiceMethod(method) 方法返回的是一个 ServiceMethod 对象,从名字上来看也可以猜出,每个 ServiceMethod 对象就对应一个 API 接口方法,其内部就包含了对 API 的解析结果。loadServiceMethod(method).invoke(args) 这个操作就对应调用 API 方法并传递参数这个过程,即对应 val call: Call<ResponseBody> = service.getUserData() 这个过程

  • ServiceMethod 是一个抽象类,仅包含一个抽象的 invoke(Object[] args) 方法。ServiceMethod 使用到了工厂模式,由于 API 的最终请求方式可能是多样化的,既可能是通过线程池来执行,也可能是通过 Kotlin 协程来执行,使用工厂模式的意义就在于可以将这种差异都隐藏在不同的 ServiceMethod 实现类中,而外部统一都是通过 parseAnnotations() 方法来获取 ServiceMethod 的实现类

  • parseAnnotations() 方法返回的 ServiceMethod 实际上是 HttpServiceMethod,所以重点就要来看 HttpServiceMethod.parseAnnotations() 方法返回的 HttpServiceMethod 具体是如何实现的,并是如何拼接出一个完整的 OkHttp 请求调用链

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    abstract class ServiceMethod<T> {
    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //requestFactory 包含了对 API 的注解信息进行解析后的结果
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    //如果返回值包含未确定的泛型类型或者是包含通配符的话,那么就抛出异常
    //因为 Retrofit 无法构造出一个不具有确定类型的对象作为返回值
    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);
    }

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

五. HttpServiceMethod

  • 通过查找引用,可以知道 ServiceMethod 这个抽象类的直接子类只有一个,即 HttpServiceMethod。HttpServiceMethod 也是一个抽象类,其包含两个泛型声明:ResponseT 表示的是 API 方法返回值的外层包装类型,ReturnT 表示的是我们实际需要的数据类型。例如,对于 fun getUserData(): Call<UserBean> 方法,ResponseT 对应的是 Call,ReturnT 对应的是 UserBean

  • 此外,HttpServiceMethod 也实现了父类的 invoke() 方法,并将操作转交给了另一个抽象方法 adapt() 来完成,所以说,API 方法对应的网络请求具体的发起操作主要看 adapt() 方法即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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);

    ···

    }
  • 再来看 HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory) 方法是如何构建出一个 HttpServiceMethod 对象的,并且该对象的 adapt() 方法是如何实现的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    /**
    * Inspects the annotations on an interface method to construct a reusable service method that
    * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
    * method only once and reuse it.
    */
    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
    //是否是 Suspend 函数,即是否以 Kotlin 协程的方式来进行请求
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
    //省略 Kotlin 协程的一些处理逻辑
    } else {
    adapterType = method.getGenericReturnType();
    }

    //重点1
    CallAdapter<ResponseT, ReturnT> callAdapter =
    createCallAdapter(retrofit, method, adapterType, annotations);

    //拿到包装类内部的具体类型,例如,Observable<UserBean> 内部的 UserBean
    //responseType 不能是 okhttp3.Response 或者是不包含具体泛型类型的 Response
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
    throw methodError(
    method,
    "'"
    + getRawType(responseType).getName()
    + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
    throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
    throw methodError(method, "HEAD method must use Void as response type.");
    }

    //重点2
    Converter<ResponseBody, ResponseT> responseConverter =
    createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
    //重点3
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    }

    //省略 Kotlin 协程的一些处理逻辑
    ···

    }

    ···

    }
  • Retrofit 目前已经支持以 Kotlin 协程的方式来进行调用了,但本例子和协程无关,所以此处先忽略协程相关的处理逻辑,后面会再讲解,parseAnnotations() 方法的主要逻辑是:

    1. 先通过 createCallAdapter(retrofit, method, adapterType, annotations) 方法拿到 CallAdapter 对象,CallAdapter 就用于实现 API 方法的不同返回值包装类处理逻辑。例如,getUserData() 方法的返回值包装类类型如果是 Call ,那么返回的 CallAdapter 对象就对应 DefaultCallAdapterFactory 包含的 Adapter;如果是 Observable,那么返回的就是 RxJava2CallAdapterFactory 包含的 Adapter
    2. 再通过 createResponseConverter(retrofit, method, responseType) 方法拿到 Converter 对象,Converter 就用于实现 API 方法的不同返回值处理逻辑。例如,getUserData() 方法的目标返回值类型如果是 ResponseBody ,那么 Converter 对象就对应 BuiltInConverters;如果是 UserBean,那么就对应 GsonConverterFactory
    3. 根据前两个步骤拿到的值,构造出一个 CallAdapted 对象并返回
  • CallAdapted 正是 HttpServiceMethod 的子类,在 InvocationHandler 中通过 loadServiceMethod(method).invoke(args) 发起的调用链,会先创建出一个 OkHttpCall 对象,并最后调用到 callAdapter.adapt(call) 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    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);
    }

    }


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

六. OkHttpCall

  • OkHttpCall 是实际发起 OkHttp 请求的地方。当我们调用 fun getUserData(): Call<ResponseBody> 方法时,返回的 Call 对象实际上是 OkHttpCall 类型,而当我们调用 call.enqueue(Callback) 方法时,enqueue() 方法中会发起一个 OkHttp 请求,传入的 Callback 对象就会由 okhttp3.Callback 本身收到回调时再进行中转调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    final class OkHttpCall<T> implements Call<T> {
    private final RequestFactory requestFactory;
    private final Object[] args;
    private final okhttp3.Call.Factory callFactory;
    private final Converter<ResponseBody, T> responseConverter;

    private volatile boolean canceled;

    @GuardedBy("this")
    private @Nullable okhttp3.Call rawCall;

    @GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
    private @Nullable Throwable creationFailure;

    @GuardedBy("this")
    private boolean executed;

    @Override
    public void enqueue(final Callback<T> callback) {
    ···
    okhttp3.Call call;
    ···
    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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
interface ApiService {

@GET("getUserData")
fun getUserData(): Call<ResponseBody>

}

fun main() {
val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.build()
val service = retrofit.create(ApiService::class.java)
val call: Call<ResponseBody> = service.getUserData()
call.enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
val userBean = response.body()?.string()
println("userBean: $userBean")
}

override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
println("onFailure: $t")
}
})
}
  • 首先,我们通过 retrofit.create(ApiService::class.java) 得到一个 ApiService 的动态实现类,这是通过 Java 原生提供的Proxy.newProxyInstance 代表的动态代理功能来实现的。在拿到 ApiService 的实现类后,我们就可以直接调用 ApiService 中声明的所有方法了

  • 当我们调用了 service.getUserData() 方法时,Retrofit 会将每一个 API 方法都抽象封装为一个 ServiceMethod 对象并缓存起来,我们的操作会转交给 ServiceMethod 来完成,由 ServiceMethod 来负责返回我们的目标类型,对应的是 ServiceMethod.invoke(Object[] args) 方法,args 代表的是我们调用 API 方法时需要传递的参数,对应本例子就是一个空数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    abstract class ServiceMethod<T> {
    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //requestFactory 包含了对 API 的注解信息进行解析后的结果
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    //如果返回值包含未确定的泛型类型或者是包含通配符的话,那么就抛出异常
    //因为 Retrofit 无法构造出一个不具有确定类型的对象作为返回值
    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);
    }

    abstract @Nullable T invoke(Object[] args);
    }
  • 实际上,ServiceMethod 只具有一个唯一的直接子类,即 HttpServiceMethod,而 HttpServiceMethod 会在 invoke() 方法中构建出一个 OkHttpCall 对象,然后调用其抽象方法 adapt()

  • 此外,对于不同的请求方式,ServiceMethod.parseAnnotations() 方法最终会返回不同的 HttpServiceMethod 子类。对应本例子,最终返回的会是 CallAdapted 对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    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> {
    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);
    }
    }
  • 所以,当我们调用 val call: Call<ResponseBody> = service.getUserData() 时,返回的 Call<ResponseBody> 实际上是 OkHttpCall<ResponseBody>

  • 当我们调用 call.enqueue() 方法时,OkHttpCall 的 enqueue() 方法内部就会发起一个 OkHttp 请求,并为这个请求设置一个回调对象 okhttp3.Callback,然后在这个回调中再来回调我们传递进去的 retrofit2.Callback。这样,外部也就可以收到网络请求成功或者失败的事件回调了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    final class OkHttpCall<T> implements Call<T> {

    @Override
    public void enqueue(final Callback<T> callback) {
    ···
    okhttp3.Call call;
    ···
    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
    }
    }
    });
    }
    }

八. API 方法是如何解析的

  • 问题一:Retrofit 是如何将 interface 内部的方法转化为一个个实际的 GET、POST、DELETE 等各式各样的网络请求的?例如,Retrofit 是如何将 getUserData() 转换为一个 OkHttp 的 GET 请求的?

  • 这个过程在 ServiceMethod 的 parseAnnotations() 方法中就已经完成的了,对应的是 RequestFactory.parseAnnotations(retrofit, method) 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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);
    }
  • 前文说了,Retrofit 是建立在 OkHttp 之上的一个网络请求封装库,内部依靠 OkHttp 来完成实际的网络请求。而 OkHttp 的一般请求方式如下所示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    OkHttpClient client = new OkHttpClient();

    String run(String url) throws IOException {
    Request request = new Request.Builder()
    .url(url)
    .build();

    try (Response response = client.newCall(request).execute()) {
    return response.body().string();
    }
    }
  • OkHttp 需要构建一个 Request 对象来配置请求方式和请求参数,并以此来发起网络请求。所以,Retrofit 也需要一个构建 Request 对象的过程,这个过程就隐藏在 RequestFactory 中

  • RequestFactory 采用了 Builder 模式,这里无需过多理会其构建过程,我们只要知道 RequestFactory 中包含了对 API 方法的各项解析结果即可。其 create(Object[] args) 方法就会根据各项解析结果,最终返回一个 okhttp3.Request 对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    final class RequestFactory {
    static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
    }

    private final Method method;
    private final HttpUrl baseUrl;
    final String httpMethod;
    private final @Nullable String relativeUrl;
    private final @Nullable Headers headers;
    private final @Nullable MediaType contentType;
    private final boolean hasBody;
    private final boolean isFormEncoded;
    private final boolean isMultipart;
    private final ParameterHandler<?>[] parameterHandlers;
    final boolean isKotlinSuspendFunction;

    okhttp3.Request create(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(method, argumentList)).build();
    }
    }
  • OkHttpCall 是实际上发起网络请求的地方,所以最终 RequestFactory 的 create() 方法会由 OkHttpCall 的 createRawCall() 方法来调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    final class OkHttpCall<T> implements Call<T> {

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

    }

九. ResponseBody 是如何映射为 UserBean 的

  • 问题二:Retrofit 是如何将 API 的返回值映射为具体的 Bean 对象的?例如,ResponseBody 是如何映射为 UserBean 的?

  • OkHttp 默认的接口返回值对象就是 ResponseBody,所以在使用 Retrofit 时如果不引入 converter-gson,我们只能将接口请求结果都定义为 ResponseBody,而不能是具体的 Bean 对象,因为 Retrofit 无法自动地完成 ResponseBody 到 UserBean 之间的转换操作,需要我们将这种转换规则告知 Retrofit

    1
    2
    3
    4
    5
    6
    7
    8
    9
    interface ApiService {

    @GET("getUserData")
    fun getUserData1(): Call<ResponseBody>

    @GET("getUserData")
    fun getUserData2(): Call<UserBean>

    }
  • 这种转换规则被 Retrofit 定义为 Converter 接口,对应它的 responseBodyConverter() 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public interface Converter<F, T> {

    @Nullable
    T convert(F value) throws IOException;

    abstract class Factory {

    //将 ResponseBody 转换为目标类型 type
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
    Type type, Annotation[] annotations, Retrofit retrofit) {
    return null;
    }
    }
    }
  • 为了能直接获取到 UserBean 对象,我们需要在构建 Retrofit 对象的时候添加 GsonConverterFactory

    1
    2
    3
    4
    val retrofit = Retrofit.Builder()
    .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
    .addConverterFactory(GsonConverterFactory.create())
    .build()
  • GsonConverterFactory 会根据目标类型 type,通过 Gson 来进行反序列化出 UserBean 对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    public final class GsonConverterFactory extends Converter.Factory {

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
    Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
    }

    ···

    }


    final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson gson;
    private final TypeAdapter<T> adapter;

    GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
    }

    @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
    T result = adapter.read(jsonReader);
    if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
    throw new JsonIOException("JSON document was not fully consumed.");
    }
    return result;
    } finally {
    value.close();
    }
    }
    }
  • 问题又来了,Retrofit 是如何知道什么类型才可以交由 GsonConverterFactory 来进行处理的?至少 ResponseBody 就不应该交由 GsonConverterFactory 来处理,Retrofit 如何进行选择?

  • 首先,当我们在构建 Retrofit 对象时传入了 GsonConverterFactory,最终 Retrofit 会对所有 Converter.Factory 进行排序,converterFactories() 中 BuiltInConverters 会被默认排在第一位,BuiltInConverters 是 Retrofit 自带的对 ResponseBody 进行默认解析的 Converter.Factory 实现类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public final class Retrofit {

    public static final class Builder {
    public Retrofit build() {

    ···

    // 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());
    }
    }
  • 而 BuiltInConverters 的 responseBodyConverter() 方法在目标类型并非 ResponseBody、Void、Unit 等三种类型的情况下会返回 null

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    final class BuiltInConverters extends Converter.Factory {

    @Override
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
    Type type, Annotation[] annotations, Retrofit retrofit) {
    if (type == ResponseBody.class) {
    return Utils.isAnnotationPresent(annotations, Streaming.class)
    ? StreamingResponseBodyConverter.INSTANCE
    : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
    return VoidResponseBodyConverter.INSTANCE;
    }
    if (checkForKotlinUnit) {
    try {
    if (type == Unit.class) {
    return UnitResponseBodyConverter.INSTANCE;
    }
    } catch (NoClassDefFoundError ignored) {
    checkForKotlinUnit = false;
    }
    }
    return null;
    }
    }
  • 而 Retrofit 类的 nextResponseBodyConverter() 方法就是为每一个 API 方法选择 Converter 进行返回值数据类型转换的方法。该方法会先遍历到 BuiltInConverters,发现其返回了 null,就会最终选择到 GsonResponseBodyConverter,从而完成数据解析。如果最终没有找到一个合适的处理器的话,就会抛出 IllegalArgumentException

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
    @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    Objects.requireNonNull(type, "type == null");
    Objects.requireNonNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
    Converter<ResponseBody, ?> converter =
    converterFactories.get(i).responseBodyConverter(type, annotations, this);
    if (converter != null) {
    //noinspection unchecked
    return (Converter<ResponseBody, T>) converter;
    }
    }
    ···
    throw new IllegalArgumentException(builder.toString());
    }

十. Call 是如何替换为 Observable 的

  • 问题三:Retrofit 是如何抽象不同的 API 返回值包装类的?例如,Call 是如何替换为 Observable 的?

  • Retrofit 在默认情况下也只支持将 retrofit2.Call 作为 API 接口的返回数据类型包装类,为了支持返回 Observable 类型,我们需要在构建 Retrofit 的时候添加 RxJava2CallAdapterFactory

    1
    2
    3
    4
    5
    val retrofit = Retrofit.Builder()
    .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()
  • Retrofit 将 retrofit2.Call 转换为 Observable 的这种规则抽象为了 CallAdapter 接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public interface CallAdapter<R, T> {

    //返回具体的内部类型,即 UserBean
    Type responseType();

    //用于将 Call 转换为 Observable
    T adapt(Call<R> call);

    abstract class Factory {

    //用于提供将 Call<UserBean> 转换为 Observable<UserBean> 的 CallAdapter 对象
    //此处的 returnType 即 Observable<UserBean>
    //如果此 CallAdapter 无法完成这种数据类型的转换,那么就返回 null
    public abstract @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit);
    }
    }
  • 对于 RxJava2CallAdapterFactory 的 get() 方法而言,如果返回值类型并非 Completable、Flowable、Single、Maybe 等类型的话就会返回 null,否则就返回 RxJava2CallAdapter 对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
    @Override
    public @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {

    Class<?> rawType = getRawType(returnType);
    if (rawType == Completable.class) {
    // Completable is not parameterized (which is what the rest of this method deals with) so it
    // can only be created with a single configuration.
    return new RxJava2CallAdapter(
    Void.class, scheduler, isAsync, false, true, false, false, false, true);
    }

    boolean isFlowable = rawType == Flowable.class;
    boolean isSingle = rawType == Single.class;
    boolean isMaybe = rawType == Maybe.class;
    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
    return null;
    }

    // ...
    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);
    }
    }
  • 对于本例子而言,最终 RxJava2CallAdapter 又会返回 CallExecuteObservable,CallExecuteObservable 又会在外部进行 subscribe() 的时候调用 call.execute() 方法来发起网络请求,所以在上面的例子中我们并不需要显式地发起网络请求,而是在进行 subscribe() 的时候就自动触发请求了,Observer 只需要等待网络请求结果自动回调出来即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {      
    @Override
    public Type responseType() {
    return responseType;
    }

    @Override
    public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable =
    isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call);

    // ...
    return RxJavaPlugins.onAssembly(observable);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    final class CallExecuteObservable<T> extends Observable<Response<T>> {
    private final Call<T> originalCall;

    CallExecuteObservable(Call<T> originalCall) {
    this.originalCall = originalCall;
    }

    @Override
    protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallDisposable disposable = new CallDisposable(call);
    observer.onSubscribe(disposable);
    if (disposable.isDisposed()) {
    return;
    }

    boolean terminated = false;
    try {
    //发起网络请求
    Response<T> response = call.execute();
    if (!disposable.isDisposed()) {
    //将请求结果传给外部
    observer.onNext(response);
    }
    if (!disposable.isDisposed()) {
    terminated = true;
    observer.onComplete();
    }
    } catch (Throwable t) {
    Exceptions.throwIfFatal(t);
    if (terminated) {
    RxJavaPlugins.onError(t);
    } else if (!disposable.isDisposed()) {
    try {
    observer.onError(t);
    } catch (Throwable inner) {
    Exceptions.throwIfFatal(inner);
    RxJavaPlugins.onError(new CompositeException(t, inner));
    }
    }
    }
    }

    // ...
    }
  • 问题又来了,Retrofit 是如何知道什么类型才可以交由 RxJava2CallAdapterFactory 来进行处理的?

  • 首先,当我们在构建 Retrofit 对象时传入了 RxJava2CallAdapterFactory,最终 Retrofit 会按照添加顺序对所有 CallAdapter.Factory 进行保存,且默认会在队尾添加一个 DefaultCallAdapterFactory,用于对包装类型为 retrofit2.Call 的情况进行解析

  • 而 Retrofit 类的 nextCallAdapter() 方法就是为每一个 API 方法选择 CallAdapter 进行返回值数据类型转换的方法。该方法会先遍历到 RxJava2CallAdapter ,发现其返回了非 null 值,之后就交由其进行处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public CallAdapter<?, ?> nextCallAdapter(
    @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
    Objects.requireNonNull(returnType, "returnType == null");
    Objects.requireNonNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
    return adapter;
    }
    }

    // ...
    throw new IllegalArgumentException(builder.toString());
    }

十一. 数据转换流程总结

  • 在默认情况下,我们从回调 Callback 中取到的最原始的返回值类型是 Response

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    interface ApiService {

    @GET("getUserData")
    fun getUserData(): Call<ResponseBody>

    }

    fun main() {
    val retrofit = Retrofit.Builder()
    .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
    .build()
    val service = retrofit.create(ApiService::class.java)
    val call: Call<ResponseBody> = service.getUserData()
    call.enqueue(object : Callback<ResponseBody> {
    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
    val userBean = response.body()?.string()
    println("userBean: $userBean")
    }

    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
    println("onFailure: $t")
    }
    })
    }
  • 而在引入了 converter-gsonadapter-rxjava2 之后,我们可以直接拿到目标类型 UserBean

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    data class UserBean(val userName: String, val userAge: Long)

    interface ApiService {

    @GET("getUserData")
    fun getUserData(): Observable<UserBean>

    }

    fun main() {
    val retrofit = Retrofit.Builder()
    .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync())
    .build()
    val service = retrofit.create(ApiService::class.java)
    val call: Observable<UserBean> = service.getUserData()
    call.subscribe(object : Consumer<UserBean> {
    override fun accept(userBean: UserBean?) {
    println("userBean: $userBean")
    }

    }, object : Consumer<Throwable> {
    override fun accept(t: Throwable?) {
    println("onFailure: $t")
    }
    })
    }
  • Retrofit 要达到这种转换效果,就要先后进行两个步骤:

    1. 将 ResponseBody转换为 UserBean,从而可以得到 API 返回值 Response<UserBean>
    2. 将 Call 转换为 Observable,Observable 直接从 Response<UserBean> 中把 UserBean 取出来作为返回值来返回,从而直接得到目标类型 UserBean
  • 第一个步骤即第九节所讲的内容,ResponseBody 转为 UserBean 的转换规则是通过 Converter 接口来定义的

    1
    2
    3
    4
    5
    6
    7
    8
    public interface Converter<F, T> {

    //用于将 F 类型转换为 T 类型
    @Nullable
    T convert(F value) throws IOException;

    // ...
    }
  • 这个过程的转换就发生在 OkHttpCall 中,enqueue() 方法在拿到 OkHttp 返回的 okhttp3.Response 对象后,就通过调用 parseResponse() 方法来完成转化为 Response<T> 的逻辑,当中就调用了 Converter 接口的 convert() 方法,从而得到返回值 Response<UserBean>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    final class OkHttpCall<T> implements Call<T> {

    @Override
    public void enqueue(final Callback<T> callback) {
    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
    }
    }
    });
    }


    private final Converter<ResponseBody, T> responseConverter;

    Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ···
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
    //catchingBody 就是 ResponseBody 类型,将其转换为 T 类型
    T body = responseConverter.convert(catchingBody);
    //然后再将其包装为 Response<T> 类型
    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;
    }
    }
    }
  • 第二个步骤即第十节所讲的内容, Call 转换为 Observable 的转换规则是通过 CallAdapter 接口来定义的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface CallAdapter<R, T> {

    Type responseType();

    //此方法就用于将 Call<R> 转为你希望的目标类型 T,例如:Observable<UserBean>
    T adapt(Call<R> call);

    //...
    }
  • 在 CallEnqueueObservable 这个类中,通过自定义回调接口 CallCallback 来发起网络请求,从而拿到在第一个步骤解析完成后的数据,即 Response<UserBean> 对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    final class CallEnqueueObservable<T> extends Observable<Response<T>> {
    private final Call<T> originalCall;

    CallEnqueueObservable(Call<T> originalCall) {
    this.originalCall = originalCall;
    }

    @Override
    protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    if (!callback.isDisposed()) {
    //自定义回调,发起请求
    call.enqueue(callback);
    }
    }

    private static final class CallCallback<T> implements Disposable, Callback<T> {
    private final Call<?> call;
    private final Observer<? super Response<T>> observer;
    private volatile boolean disposed;
    boolean terminated = false;

    CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
    this.call = call;
    this.observer = observer;
    }

    @Override
    public void onResponse(Call<T> call, Response<T> response) {
    ···
    //直接将Response<T>传递出去,即 Response<UserBean> 对象
    observer.onNext(response);
    ···
    }

    ···
    }
    }
  • CallCallback 类同时持有着一个 observer 对象,该 observer 对象实际上又属于 BodyObservable 类。BodyObservable 在拿到了 Response<UserBean> 对象后,如果判断到此次网络请求属于成功状态的话,那么就直接取出 body (即 UserBean)传递出去。因此我们才可以直接拿到目标类型,而不包含任何包装类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    final class BodyObservable<T> extends Observable<T> {
    private final Observable<Response<T>> upstream;

    BodyObservable(Observable<Response<T>> upstream) {
    this.upstream = upstream;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
    upstream.subscribe(new BodyObserver<T>(observer));
    }

    private static class BodyObserver<R> implements Observer<Response<R>> {
    private final Observer<? super R> observer;
    private boolean terminated;

    BodyObserver(Observer<? super R> observer) {
    this.observer = observer;
    }

    @Override
    public void onSubscribe(Disposable disposable) {
    observer.onSubscribe(disposable);
    }

    @Override
    public void onNext(Response<R> response) {
    if (response.isSuccessful()) {
    //如果本次网络请求成功,那么就直接取出 body 传递出去
    observer.onNext(response.body());
    } else {
    terminated = true;
    Throwable t = new HttpException(response);
    try {
    observer.onError(t);
    } catch (Throwable inner) {
    Exceptions.throwIfFatal(inner);
    RxJavaPlugins.onError(new CompositeException(t, inner));
    }
    }
    }

    ···
    }
    }

十二. Retrofit 对 Android 平台的特殊支持

  • Retrofit 的内部实现并不需要依赖于 Android 平台,而是可以用于任意的 Java 客户端,Retrofit 只是对 Android 平台进行了特殊实现而已

  • 在构建 Retrofit 对象的时候,我们可以选择传递一个 Platform 对象用于标记调用方所处的平台

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
    this.platform = platform;
    }

    public Builder() {
    this(Platform.get());
    }

    ···
    }
  • Platform 类有两个作用

    1. 判断是否支持 Java 8。这在判断是否支持调用 interface 的默认方法,以及判断是否支持 Optional 和 CompletableFuture 时需要用到。因为 Android 应用如果想要支持 Java 8 的话,是需要在 Gradle 文件中进行主动配置的,且 Java 8 在 Android 平台上目前也支持得并不彻底,所以需要判断是否支持 Java 8 来决定是否启用特定功能

    2. 实现 main 线程回调的 Executor。众所周知,Android 平台是不允许在 main 线程上执行耗时任务的,且 UI 操作都需要切换到 main 线程来完成。所以,对于 Android 平台来说,Retrofit 在回调网络请求结果时,都会通过 main 线程执行的 Executor 来进行线程切换

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      class Platform {
      private static final Platform PLATFORM = findPlatform();

      static Platform get() {
      return PLATFORM;
      }

      private static Platform findPlatform() {
      //根据 JVM 名字来判断使用方是否是 Android 平台
      return "Dalvik".equals(System.getProperty("java.vm.name"))
      ? new Android() //
      : new Platform(true);
      }

      //是否支持 Java 8
      private final boolean hasJava8Types;
      private final @Nullable Constructor<Lookup> lookupConstructor;

      Platform(boolean hasJava8Types) {
      this.hasJava8Types = hasJava8Types;

      Constructor<Lookup> lookupConstructor = null;
      if (hasJava8Types) {
      try {
      // Because the service interface might not be public, we need to use a MethodHandle lookup
      // that ignores the visibility of the declaringClass.
      lookupConstructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
      lookupConstructor.setAccessible(true);
      } catch (NoClassDefFoundError ignored) {
      // Android API 24 or 25 where Lookup doesn't exist. Calling default methods on non-public
      // interfaces will fail, but there's nothing we can do about it.
      } catch (NoSuchMethodException ignored) {
      // Assume JDK 14+ which contains a fix that allows a regular lookup to succeed.
      // See https://bugs.openjdk.java.net/browse/JDK-8209005.
      }
      }
      this.lookupConstructor = lookupConstructor;
      }

      //获取默认的 Executor 实现,用于 Android 平台
      @Nullable
      Executor defaultCallbackExecutor() {
      return null;
      }

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

      int defaultCallAdapterFactoriesSize() {
      return hasJava8Types ? 2 : 1;
      }

      List<? extends Converter.Factory> defaultConverterFactories() {
      return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
      }

      int defaultConverterFactoriesSize() {
      return hasJava8Types ? 1 : 0;
      }

      @IgnoreJRERequirement // Only called on API 24+.
      boolean isDefaultMethod(Method method) {
      return hasJava8Types && method.isDefault();
      }

      @IgnoreJRERequirement // Only called on API 26+.
      @Nullable
      Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, Object... args)
      throws Throwable {
      Lookup lookup =
      lookupConstructor != null
      ? lookupConstructor.newInstance(declaringClass, -1 /* trusted */)
      : MethodHandles.lookup();
      return lookup.unreflectSpecial(method, declaringClass).bindTo(object).invokeWithArguments(args);
      }
      }
  • Platform 类只具有一个唯一子类,即 Android 类。其主要逻辑就是重写了父类的 defaultCallbackExecutor() 方法,通过 Handler 来实现在 main 线程执行特定的 Runnable,以此来实现网络请求结果都在 main 线程进行回调

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    static final class Android extends Platform {
    Android() {
    super(Build.VERSION.SDK_INT >= 24);
    }

    @Override
    public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
    }

    @Nullable
    @Override
    Object invokeDefaultMethod(
    Method method, Class<?> declaringClass, Object object, Object... args) throws Throwable {
    if (Build.VERSION.SDK_INT < 26) {
    throw new UnsupportedOperationException(
    "Calling default methods on API 24 and 25 is not supported");
    }
    return super.invokeDefaultMethod(method, declaringClass, object, args);
    }

    static final class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(Runnable r) {
    handler.post(r);
    }
    }
    }
  • Retrofit 有个默认的 CallAdapter.Factory 接口实现类,用于对 API 返回值包装类型是 Call 的情形进行处理。DefaultCallAdapterFactory 会拿到 Platform 返回的 Executor 对象,如果 Executor 对象不为 null 且 API 方法没有标注 SkipCallbackExecutor 注解的话,就使用该 Executor 对象作为一个代理来中转所有的回调操作,以此实现线程切换。这里使用到了装饰器模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    private final @Nullable Executor callbackExecutor;

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

    @Override
    public @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit) {

    ···

    final Executor executor =
    //判断 annotations 是否包含 SkipCallbackExecutor 注解
    //有的话说明希望直接在原来的线程进行方法调用,不需要进行线程切换
    Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
    ? null
    : callbackExecutor;

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

    @Override
    public Call<Object> adapt(Call<Object> call) {
    //executor 不为 null 的话就将其作为一个中间代理
    //交由 ExecutorCallbackCall 来完成实际的回调操作
    return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
    }
    };
    }

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

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

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

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

    ···

    }
    }
-------------------- 本文结束感谢您的阅读 --------------------