深入剖析 Android 网络开源库 Retrofit 的源码详解

news2024/11/23 6:21:37

文章目录

  • 概述
  • 一、Retrofit 简介
    • Android主流网络请求库
  • 二、Retrofit 源码剖析
    • 1. Retrofit 网络请求过程
    • 2. Retrofit 实例构建
      • 2.1 Retrofit.java
      • 2.2 Retrofit.Builder()
        • 2.2.1 Platform.get()
        • 2.2.2 Android 平台
      • 2.3 Retrofit.Builder().baseUrl()
      • 2.4 Retrofit.Builder.client()
      • 2.5 Retrofit.Builder.addConverterFactory()
        • 2.5.1 GsonConverterFactory.create()
      • 2.6 Retrofit.Builder.addCallAdapterFactory()
        • 2.6.1 RxJava2CallAdapterFactory.create()
      • 2.7 Retrofit.Builder.build()
    • 3. Retrofit 创建网络请求接口实例
      • 3.1 Retrofit.create()
      • 3.2 Retrofit.loadServiceMethod()
      • 3.3 ServiceMethod.parseAnnotations()
        • 3.3.1 RequestFactory.parseAnnotations()
      • 3.4 HttpServiceMethod.parseAnnotations()
        • 3.4.1 HttpServiceMethod.createCallAdapter()
        • 3.4.2 Retrofit.callAdapter()
        • 3.4.3 HttpServiceMethod.createResponseConverter()
        • 3.4.4 Retrofit.responseBodyConverter()
        • 3.4.5 GsonConverterFactory.responseBodyConverter()
        • 3.4.6 GsonResponseBodyConverter
      • 3.5 HttpServiceMethod
      • 3.6 OkHttpCall
      • 3.7 RxJava2CallAdapter.adapt()
      • 小结
    • 4. Retrofit 执行网络请求
      • 4.1 Observable.subscribe()
      • 4.2 BodyObservable.subscribeActual()
      • 4.3 CallObservable.subscribeActual()
      • 4.4 OkHttpCall.execute()
        • 4.4.1 RequestFactory.create()
        • 4.4.2 OkHttpClient.newCall()
        • 4.4.3 RealCall.newRealCall()
      • 4.5 OkHttpCall.parseResponse()
        • 4.5.1 GsonResponseBodyConverter.convert()
        • 4.5.2 Gson.getAdapter()
        • 4.5.3 ReflectiveTypeAdapterFactory.Adapter.read()
      • 4.6 Response.success()
    • 小结
  • 总结
  • 参考


概述

Android 开发中,通过网络请求获取服务端数据是一项基本且常见的需求。目前有多种网络请求框架可供选择,其中 Android-Async-HttpVolleyOkHttpRetrofit 是较为流行的、开源的网络请求框架。如何选择它们?孰优孰劣?仁者见仁智者见智,我个人觉得适合的就是最好的,不要盲目跟风去更换掉之前选用的网络请求框架,毕竟老代码那是牵一发而动全身哈!对于新项目来说,选择一个好用的网络请求框架,还是很有必要的,而 Retrofit 作为当下最火的一个网络开源请求库,还是值得学习并尝试使用的。


一、Retrofit 简介

Retrofit 是一个在 Android 开发中常用的网络请求框架。是 Square 公司基于他们自己的另一个比较火的网络库 OkHttp,进行封装的一个 RESTfulHTTP 网络请求框架。其提供了简洁而强大的 API,用于与 RESTful 服务进行通信。

  • App 应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、HeaderUrl 等信息,之后由 OkHttp 完成后续的请求操作;
  • 请求获取到服务端的响应后,OkHttp 将服务端返回的、原始的数据交给 RetrofitRetrofit 再根据用户的需求对结果进行解析。

Retrofit 的一些主要特点和优势:

  • 简单易用的 APIRetrofit 提供了简洁、直观的 API,使得定义和执行网络请求变得非常简单。通过定义接口,并使用注解来描述请求参数和响应数据,可以轻松地与 RESTful API 进行交互;
  • 自动化网络请求处理Retrofit 处理了大部分网络请求的细节,包括请求的构建、执行、响应的解析等,大大简化了网络请求的代码编写过程;
  • 内置支持 RxJavaRetrofit 2.0 内置支持 RxJava,可以方便地将网络请求转换为 ObservablesSingles,实现更加优雅的异步编程模式;
  • 请求和响应的数据转换Retrofit 支持多种数据格式的转换,包括:GsonJSONXMLProtobuf 等,可以方便地进行数据的序列化和反序列化;
  • 灵活的请求配置Retrofit 允许你配置全局的请求参数,包括:连接超时读取超时请求头日志输出等,以满足不同场景下的需求;
  • 强大的错误处理机制Retrofit 提供了灵活的错误处理机制,可以根据不同的 HTTP 状态码和错误情况进行统一处理,使得应用程序在遇到错误时能够优雅地处理并给出相应的提示。

Retrofit 与其它主流网络请求库之间的功能与区别:

Android主流网络请求库

二、Retrofit 源码剖析

1. Retrofit 网络请求过程

Retrofit 请求网络的过程
结合上图,解释一下 Retrofit 网络请求过程:

  1. 通过解析网络请求接口的注解配置网络请求参数
  2. 通过动态代理生成网络请求对象
  3. 通过网络请求适配器将网络请求对象进行平台适配(包括:AndroidRxJavaGuavaJava8
  4. 通过网络请求执行器发送网络请求
  5. 通过数据转换器解析服务器返回的数据
  6. 通过回调执行器切换线程(子线程切到主线程)
  7. 用户在主线程处理并展示返回结果

本文不准备详细介绍 Retrofit 的使用,主要是深入源码剖析其原理,下面就根据上面的请求过程,逐步剖析 Retrofit 的源码调用过程,注意:后续的源码基于 Retrofit 2.5.0 版本进行分析。

2. Retrofit 实例构建

Retrofit 实例是使用建造者模式通过 Builder 类进行创建的:

OkHttpClient client = new OkHttpClient.Builder()
		.addInterceptor(new TokenHeaderInterceptor()) // 动态添加token
		.addInterceptor(new NullResponseInterceptor()) // 返回空字符的时候显示
		.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
		.writeTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
		.readTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
		.build();
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(mBaseUrl)
        .client(client) // okhttp实例对象
        .addConverterFactory(GsonConverterFactory.create()) // 添加转换器工厂
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 请求指定适配器 RxJava
        .build();

2.1 Retrofit.java

public final class Retrofit {
  // 网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象)
  // 作用:存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
  // 网络请求执行器的工厂,其作用是生产网络请求执行器 Call,Retrofit 默认使用 OkHttp
  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl; // 网络请求的 url 基地址
  // 存放数据转换器工厂的集合,数据转换器工厂是用来生产数据转换器(Converter)
  final List<Converter.Factory> converterFactories;
  // 存放网络请求适配器工厂的集合,网络请求适配器工厂是用来生产网络请求适配器(CallAdapter)
  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 的构造函数构建一个 Retrofit 实例对象,并配置好类里面的各成员变量。

工厂模式:设计模式中工厂模式,是将”类实例化的操作”与“使用对象的操作”分开,使得使用者不用知道具体参数就可以实例化出所需要的“产品”类。

2.2 Retrofit.Builder()

public final class Retrofit {
  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() {
      // 继续调用自身有参的构造方法,并通过调用 Platform.get() 方法传入了 Platform 对象
      this(Platform.get());
    }
  }
}

静态内部类 Builder 的成员变量与 Retrofit 类的成员变量是对应的,通过 Builder 类对 Retrofit 类的成员变量进行赋值。

建造者模式:将一个复杂对象的构建与表示分离,使得用户在不知道对象的创建细节情况下就可以直接创建复杂的对象。

2.2.1 Platform.get()
class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
  	// PLATFORM 是一个静态的 final 类型的变量,通过 findPlatform() 方法来赋值
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      // 通过 Class.forName(),JVM 查找并加装指定的类(即 Java 会执行该类的静态代码段)
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
      	// 如果是 Android 平台,就创建并返回一个 Android 对象并返回
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      // 支持 Java 8
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
}

由 Platform.get() 方法可以看出,Retrofit 2.5 目前支持 AndroidJava 平台,翻看之前 2.0 版本的代码,那会儿还支持 iOS 平台。在方法中通过判断返回对应平台的实例对象,这里返回的是 Android 的实例对象,即指定了运行平台为 Android

2.2.2 Android 平台
class Platform {
  static class Android extends Platform {

    @Override public Executor defaultCallbackExecutor() {
      // 新建并返回 MainThreadExecutor 实例作为默认的回调方法执行器
      return new MainThreadExecutor();
    }
    // Retrofit 中提供了四种 CallAdapterFactory:ExecutorCallAdapterFactory(默认)、
    // GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory
    @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
        @Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      // 创建默认的网络请求适配器工厂,生产的 adapter 使得 Call 在异步调用时在指定的 Executor 上执行回调
      ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
      return Build.VERSION.SDK_INT >= 24
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
    }

    @Override int defaultCallAdapterFactoriesSize() { // 默认请求适配器工厂数量
      return Build.VERSION.SDK_INT >= 24 ? 2 : 1; // 大于7.0 2 个 其他 1 个
    }

    @Override List<? extends Converter.Factory> defaultConverterFactories() { // 默认转换器工厂
      return Build.VERSION.SDK_INT >= 24
          ? singletonList(OptionalConverterFactory.INSTANCE)
          : Collections.<Converter.Factory>emptyList();
    }

    @Override int defaultConverterFactoriesSize() { // 默认转换器数量
      return Build.VERSION.SDK_INT >= 24 ? 1 : 0; // 大于7.0 1 个 其他 0 个
    }
    
    static class MainThreadExecutor implements Executor {
      // 使用 Android 主线程的 Looper 来新建一个 Handler
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
      	// 通过上面新建的 Handler 发送消息,将消息发送到UI主线程,在UI线程对网络请求返回数据进行处理
        handler.post(r);
      }
    }
  }
}

至此,RetrofitBuilder 类介绍完毕,通过跟踪查看代码可知,在 Builder 类中设置了默认的平台类型对象:Android、网络请求适配器工厂:CallAdapterFactoryCallAdapter 用于对原始 Call 进行再次封装,如结合 RxJava 使用时将 Call 封装成 Observable)、数据转换器工厂:ConverterFactory 和回调执行器:CallbackExecutor

注意:这里只是设置了默认值,但未真正配置到具体的 Retrofit 类的成员变量当中。

2.3 Retrofit.Builder().baseUrl()

public final class Retrofit {
  public static final class Builder {
	......
    private @Nullable HttpUrl baseUrl;
	......
    
    // 配置 Retrofit 类的网络请求基地址 baseUrl
    public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      // 通过 HttpUrl.get() 方法把 String 类型的 url 参数转化为适合 OkHttp 的 HttpUrl 类型
      return baseUrl(HttpUrl.get(baseUrl));
    }
    
    public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      // 把 baseUrl 参数分割成几个路径碎片
      List<String> pathSegments = baseUrl.pathSegments();
      // 通过检测最后一个 Segment 来检查 baseUrl 参数是不是以"/"结尾,不是则抛出异常
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }
  }
}

通过 HttpUrl.get() 方法把 String 类型的 url 参数转化为适合 OkHttpHttpUrl 类型,然后调用 baseUrl() 方法传入刚转化的 HttpUrl,并通过检测最后一个 Segment 来检查传入的参数是不是以 “/” 结尾,如果是则赋值保存传入的 HttpUrl,不是则抛出异常。

2.4 Retrofit.Builder.client()

public final class Retrofit {
  public static final class Builder {
    private @Nullable okhttp3.Call.Factory callFactory;
	......
    // 用于请求的 HTTP 客户端,OkHttpClient 是 Call.Factory 接口的实现类
    public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }

    // 为创建 Call 实例指定一个自定义调用工厂,设置 client 时自动设置 Call.Factory
    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
    }
  }
}

Retrofit.Builder.client() 方法为创建网络请求 Call 指定一个自定义调用工厂,这里注意:OkHttpClientCall.Factory 接口的实现类。

2.5 Retrofit.Builder.addConverterFactory()

public final class Retrofit {
  public static final class Builder {
	......
	private final List<Converter.Factory> converterFactories = new ArrayList<>();
	......
    // 为对象的序列化和反序列化添加数据转换器工厂
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
  }
}

Builder.addConverterFactory() 方法为对象的序列化和反序列化添加数据转换器工厂 ConverterFactory,下面以 GsonConverterFactory 为例,调用 GsonConverterFactory.create() 方法来创建实例对象。

2.5.1 GsonConverterFactory.create()
public final class GsonConverterFactory extends Converter.Factory {
  // 使用默认的 Gson 实例创建一个 GsonConverterFactory 实例用于数据转换
  // 编码到 JSON 并从 JSON 解码(当头部没有指定字符集时)将使用UTF-8
  public static GsonConverterFactory create() {
    // 继续调用重载的 create() 方法并传入一个新建的 Gson 实例
    return create(new Gson());
  }

  // 重载的 create() 方法,作用与上面的类似
  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    // 创建一个含有 Gson 实例对象的 GsonConverterFactory
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }

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

  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}

GsonConverterFactory.creat() 方法中创建了一个含有 Gson 实例的 GsonConverterFactory 实例对象, 并返回给 Builder.addConverterFactory() 方法作为方法的入参将其放入到 converterFactories 集合中。

2.6 Retrofit.Builder.addCallAdapterFactory()

public final class Retrofit {
  public static final class Builder {
	......
	private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
	......
    // 添加网络请求 Call 的适配器工厂,以支持除 Call 以外的服务方法返回类型
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
  }
}

Builder.addCallAdapterFactory() 方法为网络请求 Call 添加适配器工厂,以支持除 Call 以外的服务方法返回类型。本文以 RxJava2CallAdapterFactory 为例,调用 RxJava2CallAdapterFactory.create() 方法来创建实例对象。

2.6.1 RxJava2CallAdapterFactory.create()
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
  public static RxJava2CallAdapterFactory create() {
    // 继续调用 RxJava2CallAdapterFactory 有参构造方法,只是 Scheduler 传入为 null
    return new RxJava2CallAdapterFactory(null);
  }
  
  private final Scheduler scheduler;
  private RxJava2CallAdapterFactory(Scheduler scheduler) {
    this.scheduler = scheduler;
  }
  
  @Override
  public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType); // 获取当前方法参数的具体类型

    if (rawType == Completable.class) { // 返回类型是否是Completable类
      // Completable 没有参数化(这是该方法的其余部分所处理的),因此只能用单个配置创建它
      return new RxJava2CallAdapter(Void.class, scheduler, false, true, false, false, false, true);
    }
	// 由于本文是结合 RxJava 进行使用的,因此返回值类型是 Observable 类型的
    boolean isFlowable = rawType == Flowable.class; // isFlowable 为 false
    boolean isSingle = rawType == Single.class; 	// isSingle 为 false
    boolean isMaybe = rawType == Maybe.class; 		// isMaybe 为 false
    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
      return null; // 不是 Completable、Flowable、Single、Maybe 和 Observable 则返回 null
    }

    boolean isResult = false;
    boolean isBody = false;
    Type responseType;
    if (!(returnType instanceof ParameterizedType)) { // 非参数化类型
      String name = isFlowable ? "Flowable" : isSingle ? "Single" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized"
          + " as " + name + "<Foo> or " + name + "<? extends Foo>");
    }
	// 获取泛型参数的上界
    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    Class<?> rawObservableType = getRawType(observableType); // 获取当前方法参数的具体类型
    if (rawObservableType == Response.class) { // 如果是 Response
      if (!(observableType instanceof ParameterizedType)) { // 非参数化类型 抛出异常
        throw new IllegalStateException("Response must be parameterized"
            + " as Response<Foo> or Response<? extends Foo>");
      }
      // 获取当前返回类型的具体类型
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
    } else if (rawObservableType == Result.class) { // 如果是 Result 
      if (!(observableType instanceof ParameterizedType)) { // 非参数化类型 抛出异常
        throw new IllegalStateException("Result must be parameterized"
            + " as Result<Foo> or Result<? extends Foo>");
      }
      // 获取当前返回类型的具体类型
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      isResult = true;
    } else { // 如果都不符合,则默认情况下返回值类型为 observableType
      responseType = observableType;
      isBody = true; // isBody 置为 true
    }
	// 根据上面的值,实例化 RxJava2CallAdapter 对象
    return new RxJava2CallAdapter(responseType, scheduler, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }
}

RxJava2CallAdapterFactory.creat() 方法中创建 RxJava2CallAdapterFactory 实例对象, 并返回给 Builder.addCallAdapterFactory() 方法作为方法的入参将其放入到 callAdapterFactories 集合中。

2.7 Retrofit.Builder.build()

public final class Retrofit {
  public static final class Builder {
	......
    private @Nullable HttpUrl baseUrl;
	......
    Builder(Platform platform) {
      this.platform = platform;
    }
    
    /**
     * 使用配置的值创建 Retrofit 实例
     * 注意:如果 client() 方法和 callFactory() 方法都没有被调用,那么默认的 OkHttpClient 将被创建和使用
     */
    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) { 
      	// 如果没有指定 callFactory,则创建并配置默认的网络请求执行器 OkHttpClient
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
      	// 如果没有指定 callbackExecutor,则使用 platform 默认的回调执行器
      	// Android 平台默认是 MainThreadExecutor
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 创建 CallAdapterFactory 的副本,并将 platform 默认的 CallAdapterFactories 添加到集合的末尾
      // 即 CallAdapterFactory 存储顺序:自定义 CallAdapterFactory 根据添加顺序优先执行,默认的 CallAdapterFactory 最后执行
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // 创建 ConverterFactory 的副本,其集合的长度 size 是 platform 默认的 defaultConverterFactoriesSize
      // 加上当前 this.converterFactories.size() 再加 1
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // 首先添加内置的转换器工厂,其次是 GsonConverterFactory(添加到集合的第二位),最后是platform默认的 defaultConverterFactories
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      // 新建并返回一个 Retrofit 实例对象,传入上述已经配置好的成员变量
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
  }
}

Builder.build() 方法,通过已经配置好的成员变量,创建并返回一个 Retrofit 实例对象。至此,Retrofit 实例创建完毕,各项配置也已配置好,接下来通过创建网络请求接口实例,来分析 Retrofit 源码的创建过程。

3. Retrofit 创建网络请求接口实例

这里以最简单的获取用户信息为例,没有结合 RxJava 也没有任何的二次封装,越简单越容易理解。
首先,定义接收网络数据的用户信息类:

public class UserInfoBean implements Serializable {
    private String user_name;       // 用户名
    private String user_id;         // 用户ID
    ......
}

接着,定义网络请求的接口类:

public interface Api {
    @GET(“api/userInfo”) // 获取用户信息
    Observable<UserInfoBean> getUserInfo(@Query("user_id") long user_id); // 请求网络数据的接口方法
}

注解 GET:表示使用 Get 方法发送网络请求,括号里面是网络请求的 URL 地址,Retrofit 把网络请求的 URL 分成了两部分:baseUrl 放在创建 Retrofit 对象时设置(参考前面 Retrofit 的构建);另一部分在网络请求接口设置(即这里)。

注意:如果接口里的 URL 是一个完整的网址,那么在创建 Retrofit 实例对象时设置的基地址 baseUrl 可以不设置。

返回值类型是:Observable,UserInfoBean 是解析得到的数据类型,如果不结合 RxJava 使用,则返回值类型是 Call。

最后,使用前面构建的 Retrofit 实例对象,创建接口类实例请求网络数据;

// 传入网络请求的接口类,通过 Retrofit.create() 方法创建网络请求接口的实例对象
Api serviceApi = retrofit.create(Api.class);
// 由网络请求接口实例对象,对发送请求的信息进行封装,生成最终的网络请求对象
Observable<UserInfoBean> userInfo = serviceApi.getUserInfo(user_id); 

3.1 Retrofit.create()

public final class Retrofit {
  final boolean validateEagerly;
  
  @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) { // 判断是否需要提前验证
      // eagerlyValidateMethods() 方法的作用是:
      // 1.给接口中每个方法的注解进行解析并得到一个 ServiceMethod 对象
      // 2.以 Method 为键将解析得到的对象存入 LinkedHashMap 集合中
      // 注意:如果不是提前验证则进行动态解析对应方法得到一个 ServiceMethod 对象,最后存入到LinkedHashMap集合中,类似延迟加载(默认)
      eagerlyValidateMethods(service);
    }
    // 创建网络请求接口的动态代理对象,即通过动态代理创建网络请求接口的实例并返回
    // 该动态代理是为了拿到网络请求接口实例上所有的注解
    // 该方法解读为:getProxyClass0(loader, interfaces).getConstructor(constructorParams)
    // .newInstance(new Object[]{InvocationHandler})
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() { // 将代理类的实现交给 InvocationHandler 类作为具体的实现
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

		  // invoke() 方法,执行真正的逻辑(如再次转发给真正的实现类对象),还可以进行一些有用的操作
		  // 如统计执行时间、进行初始化和清理、对接口调用进行检查等。
          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // 如果该方法是 Object 中的方法,则正常调用即可
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) { // Android 平台没有重写该方法,因此不支持该操作
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            // 由于是接口中的方法,不会走上面两个分支,流程转交给 Retrofit.loadServiceMethod() 方法进行处理
            // 获取到 ServiceMethod 实例对象后,调用 ServiceMethod.invoke() 方法
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }
  
  // 该方法的主要作用是提前验证指定的方法是不是接口的默认方法,如果不是接口的默认方法,则遍历 service.getDeclaredMethods() 
  // 方法获取到的方法数组,并对其中的每一个 Method 调用 loadServiceMethod() 方法
  private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      // 检查指定的方法 method 是否是接口的默认方法
      if (!platform.isDefaultMethod(method)) {
      	// 如果不是接口的默认方法,则遍历 service.getDeclaredMethods() 方法获取的方法数组
      	// 对其中的每一个 Method 通过 loadServiceMethod() 方法加载并解析其注解
        loadServiceMethod(method);
      }
    }
  }
}

Retrofit.create() 方法首先判断是否需要提前验证接口中的方法,如果不需要,则通过动态代理创建网络请求接口的实例并返回,通过动态生成的代理类调用 interfaces 接口的方法。实际上是通过调用 InvocationHandler对象的 invoke() 方法来完成指定的功能。也就是当 Api 对象调用 getUserInfo() 接口方法时会进行拦截,调用会集中转发到 InvocationHandler.invoke() 方法进行集中处理,如:接口的统一配置,也就是注解的解析和网络请求参数的拼接。

在 InvocationHandler.invoke() 方法中,由于此时是接口中的方法,不会走上面两个判断分支,因此流程转交给 Retrofit.loadServiceMethod() 方法来获取网络请求接口方法的 ServiceMethod 实例对象,然后继续调用 ServiceMethod.invoke() 方法进行处理。

3.2 Retrofit.loadServiceMethod()

public final class Retrofit {
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
  ServiceMethod<?> loadServiceMethod(Method method) {
  	// 首先从 serviceMethodCache 缓存中获取方法对应的 ServiceMethod
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result; // 如果不为null,则直接返回该 ServiceMethod

    synchronized (serviceMethodCache) { // Map 集合中不存在,加锁进行处理,保证方法的唯一性
      result = serviceMethodCache.get(method); // 再一次进行获取
      if (result == null) { // 当前方法依旧不存在
      	// 如果 serviceMethodCache 集合中没有找到对应的 ServiceMethod
      	// 通过 ServiceMethod.parseAnnotations() 方法解析注解获取 ServiceMethod
        result = ServiceMethod.parseAnnotations(this, method);
        // 将解析获取到的 ServiceMethod,以键值对<Method, ServiceMethod>存入 serviceMethodCache 集合中
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
}

Retrofit.loadServiceMethod() 方法的主要作用是对接口中的指定方法的注解进行解析得到一个 ServiceMethod 对象,其内部通过 ServiceMethod.parseAnnotations() 方法来完成对指定的 Method 方法的注解进行解析,最后将解析获取到的 ServiceMethod,以键值对<Method, ServiceMethod>存入 serviceMethodCache 缓存集合中。

3.3 ServiceMethod.parseAnnotations()

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
  	// RequestFactory.parseAnnotations() 方法内部通过 Builder 建造者模式来构建 RequestFactory 实例对象
  	// 对当前方法的所有信息进行解析:方法上的注解、方法参数注解、方法参数值等一系列的解析
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
	// 获取 Method 方法的返回类型
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) { // 判断返回类型是否是 T 或者 通配符类型
      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.");
    }
	// 将新建的 RequestFactory 实例和 Retrofit、Method 实例一起转交给 HttpServiceMethod.parseAnnotations() 方法处理
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract T invoke(Object[] args);
}

ServiceMethod 是一个抽象类,既有实体方法也有抽象方法。在其实体方法 parseAnnotations() 中,首先通过 RequestFactory.parseAnnotations() 方法传入 Retrofit 实例和 Method 实例,构建一个 RequestFactory 实例对象,最后将新建的 RequestFactory 实例和 RetrofitMethod 实例一起转交给 HttpServiceMethod.parseAnnotations() 方法处理。

3.3.1 RequestFactory.parseAnnotations()
final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
  	// 使用建造者模式来构建 RequestFactory 实例对象
    return new Builder(retrofit, method).build();
  }
  
  RequestFactory(Builder builder) {
    method = builder.method; // 网络请求方法
    baseUrl = builder.retrofit.baseUrl; // 请求基地址
    httpMethod = builder.httpMethod; // 请求方式,如:get
    relativeUrl = builder.relativeUrl; // 请求相对路径 url
    headers = builder.headers; // 请求头数据
    contentType = builder.contentType; // 内容类型
    hasBody = builder.hasBody; // 是否有请求体
    isFormEncoded = builder.isFormEncoded; // 是否是表单提交
    isMultipart = builder.isMultipart; // 是否是表单提交(含有文件)
    parameterHandlers = builder.parameterHandlers; // 所有参数数据
  }
  ......
  static final class Builder {
    final Retrofit retrofit; // retrofit 实例对象
    final Method method; // 当前网络请求接口方法 
    final Annotation[] methodAnnotations; // 获取当前网络请求方法注解集合 eg:@POST
    final Annotation[][] parameterAnnotationsArray; // 当前网络请求方法传入参数的注解集合 eg (@Query("name") String name)
    final Type[] parameterTypes; // 当前网络请求方法传入参数类型集合 eg (String url) String.class 
    
    @Nullable ParameterHandler<?>[] parameterHandlers;
    
    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      // 获取当前方法传入参数类型集合 eg (String url) String.class 
      // 如果当前数据传入的参数有泛型类型的参数,这个方法可以返回泛型的完整信息 eg:(List<String> list) java.util.List<java.lang.String>
      // getParameterTypes(); 这个方法仅返回泛型信息 eg:(List<String> list) java.util.List
      this.parameterTypes = method.getGenericParameterTypes();
      // 获取当前网络请求方法传入参数的注解集合 eg (@Query("name") String name)
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }
    
    RequestFactory build() {
      for (Annotation annotation : methodAnnotations) { // 遍历网络请求方法上面的注解集合
        parseMethodAnnotation(annotation);  // 解析注解
      }
      if (httpMethod == null) { // 请求方式注解是否为null
        throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) { // 是否有请求体,parseMethodAnnotation 由这个方法体现:DELETE、GET、OPTIONS、HEAD为 false
        if (isMultipart) { // 没有请求体但是是表单提交(带有文件)
          throw methodError(method,
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) { // 是否是表单提交
          throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }
      int parameterCount = parameterAnnotationsArray.length; // 参数注解数组长度
      parameterHandlers = new ParameterHandler<?>[parameterCount]; // 创建ParameterHandler集合对象
      for (int p = 0; p < parameterCount; p++) {
        // 对参数注解进行逐一解析
        parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
      }
	  ......
	  // 实例化请求工厂对象
      return new RequestFactory(this);
    }
  }
}

RequestFactory.parseAnnotations() 方法内部通过 Builder 建造者模式来构建 RequestFactory 实例对象,通过对当前网络请求方法的所有信息进行解析:方法上的注解、方法参数注解、方法参数值等一系列的解析后保存起来。

3.4 HttpServiceMethod.parseAnnotations()

/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  // 检查接口方法上的注释,以构造一个可重复使用的 HTTP 服务方法
  // 由于要用到反射,开销较大,因此每个服务方法只构建一次然后重用它
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    // 通过 createCallAdapter() 方法创建 CallAdapter 实例对象
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType(); // 获取响应数据类型 
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    // 请求方法是请求头 并且方法返回不为 Void
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }
	// 通过 createResponseConverter() 方法创建 Converter 实例对象用于解析服务端返回的数据
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
	// callFactory 就是开始初始化的 OkHttpClient
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    // 使用入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }
}

HttpServiceMethod.parseAnnotations() 方法,首先通过 createCallAdapter() 方法创建 CallAdapter 实例对象,然后通过 createResponseConverter() 方法创建 Converter 实例对象用于解析服务端返回的数据,最后使用入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象。

3.4.1 HttpServiceMethod.createCallAdapter()
/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  ......
  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method) {
    Type returnType = method.getGenericReturnType();    // 获取网络请求接口里方法的返回值类型
    Annotation[] annotations = method.getAnnotations(); // 获取网络请求接口里的注解,示例代码中是 @GET
    try {
      // 根据获取的 returnType 和 annotations,通过 retrofit.callAdapter() 方法获取 CallAdapter
      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);
    }
  }
}

HttpServiceMethod.createCallAdapter() 方法的主要作用是,根据获取的网络请求接口方法的返回值类型 returnTypeannotations 注解,通过 Retrofit.callAdapter() 方法从 Retrofit 对象中获取对应的网络请求适配器 CallAdapter 实例对象。

3.4.2 Retrofit.callAdapter()
public final class Retrofit {
  final List<CallAdapter.Factory> callAdapterFactories;

  // 从可用的 callAdapterFactories 工厂集合中返回指定 returnType 的 CallAdapter 实例对象
  // 构造 Retrofit 实例对象时进行添加的 CallAdapter.Factory
  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    // 继续调用 nextCallAdapter() 方法来获取 CallAdapter 实例对象
    return nextCallAdapter(null, returnType, annotations);
  }

  // 从可用的 callAdapterFactories 工厂集合中(skipPast 除外)返回指定 returnType 的 CallAdapter 实例对象
  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      // 遍历 callAdapterFactories 集合寻找对应的工厂,进而再找出符合条件的 CallAdapter 并返回
      // 由于构造 Retroifit 实例对象时添加的是 RxJava2CallAdapterFactory,因此这里获取到的就是 RxJava2CallAdapterFactory 工厂
      // 由 RxJava2CallAdapterFactory.get()方法根据网络请求接口方法的返回值类型和注解,返回符合条件的 RxJava2CallAdapter 实例对象
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
	// 如果最终没有找到工厂来提供需要的 CallAdapter,则拼接并抛出异常信息
    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }
}

Retrofit.callAdapter() 方法将获取指定 returnTypeannotations 注解的 CallAdapter 实例对象的任务转交给 Retrofit.nextCallAdapter() 方法进行查找,找到符合条件的 CallAdapter 实例对象则直接返回,否者抛出报错信息。

3.4.3 HttpServiceMethod.createResponseConverter()
/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  ......
  private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
      // 根据入参 responseType 及获取的 annotations,通过 retrofit.responseBodyConverter() 方法获取 Converter
      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);
    }
  }
}

HttpServiceMethod.createResponseConverter() 方法的主要作用是,根据入参 responseType 及获取的方法的 annotations 注解,通过 retrofit.responseBodyConverter() 方法从 Retrofit 对象中获取对应的数据转换器 Converter 实例对象。

3.4.4 Retrofit.responseBodyConverter()
public final class Retrofit {
  final List<Converter.Factory> converterFactories;
  
  // 从可用的 converterFactories 工厂集合中为 ResponseBody 找到指定 type 的 Converter 实例对象
  // 构造 Retrofit 实例对象时进行添加的 Converter.Factory
  public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }

  // 从可用的 converterFactories 工厂集合中为 ResponseBody 找到指定 type 的 Converter 实例对象(除了 skipPast)
  public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      // 遍历 converterFactories 集合寻找对应的工厂,进而再找出符合条件的 Converter 并返回
      // 由于构造 Retroifit 实例对象时采用的是 Gson 解析方式,所以先取出的是 GsonConverterFactory 工厂
      // 由 GsonConverterFactory.responseBodyConverter()方法根据 responseType 类型和注解
      // 返回符合条件的 GsonResponseBodyConverter 实例对象
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }
	// 如果最终没有找到工厂来提供需要的 Converter,则拼接并抛出异常信息
    StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
        .append(type)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }
}

Retrofit.responseBodyConverter() 方法将为 ResponseBody 获取指定 typeConverter 实例对象的任务转交给 Retrofit.nextResponseBodyConverter() 方法进行查找,找到符合条件的 Converter 实例对象则直接返回,否者抛出报错信息。

3.4.5 GsonConverterFactory.responseBodyConverter()
public final class GsonConverterFactory extends Converter.Factory {
  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    // 根据目标类型,利用 Gson.getAdapter() 方法获取相应的 adapter
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    // 使用创建 GsonConverterFactory 时保存的 gson 实例和 adapter 新建 GsonResponseBodyConverter 实例对象
    return new GsonResponseBodyConverter<>(gson, adapter);
  }
}

GsonConverterFactory.responseBodyConverter() 方法中根据目标类型,利用 Gson.getAdapter() 方法获取相应的 adapter,随后使用创建 GsonConverterFactory 时保存的 gson 实例和 adapter 新建 GsonResponseBodyConverter 实例对象。

3.4.6 GsonResponseBodyConverter
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  // 用于数据解析的主要类,内部采用工厂设计模式来实现不同 TypeAdapter 的创建,其成员变量fatories保存了
  // TypeAdapterFactory 列表,成员函数 getAdapter(type) 方法则根据不同的 type 去匹配 factories 中的一个工厂类,
  // 然后调用该工厂类的 create() 方法得到一个相应的 TypeAdapter 对象
  private final Gson gson;
  private final TypeAdapter<T> adapter;	 // TypeAdapter是一个抽象类,定义了转换的顶层接口,具体功能是在其子类中实现的

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

  @Override public T convert(ResponseBody value) throws IOException {
  	// 通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      // TypeAdapter.read() 方法将 Json 数据流解析成结构化对象T,其内部是通过 fromJson()方法
      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();
    }
  }
}

GsonResponseBodyConverter 类实现了 Converter 接口,在其实现的 convert() 方法中,首先通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入,然后通过 TypeAdapter.read() 方法将 Json 数据流解析成结构化对象 T 并返回,其内部是通过 fromJson()方法实现的。

HttpServiceMethod.parseAnnotations() 方法的最后根据入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象并返回给代理对象 InvocationHandler.invoke() 方法最后调用的 Retrofit.loadServiceMethod() 方法,进而继续调用 HttpServiceMethod.invoke() 方法。

3.5 HttpServiceMethod

/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  ......
  private final RequestFactory requestFactory;	 // 解析注解构造的请求工厂数据,里面有method,baseUrl,httpMethod等
  private final okhttp3.Call.Factory callFactory;	// 默认为 OkHttpClient 对象
  private final CallAdapter<ResponseT, ReturnT> callAdapter;   // 用于适配 OkHttpCall 的网络请求适配器
  private final Converter<ResponseBody, ResponseT> responseConverter;   // 用于解析响应的数据转换器 Converter 

  // 构建 HttpServiceMethod 的实例对象,并保存入参到其成员变量中
  private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
      CallAdapter<ResponseT, ReturnT> callAdapter,
      Converter<ResponseBody, ResponseT> responseConverter) {
    this.requestFactory = requestFactory;
    this.callFactory = callFactory;
    this.callAdapter = callAdapter;
    this.responseConverter = responseConverter;
  }

  @Override ReturnT invoke(Object[] args) {
  	// 由前面的分析可知,这里调用的是 RxJava2CallAdapter.adapt() 方法,并新建 OkHttpCall 实例对象作为方法的入参
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }
}

HttpServiceMethod 是抽象类 ServiceMethod 的具体实现,用来存储一次网络请求的基本信息,比如:HostURL、请求方法等,还会存储用来适配 OkHttpCall 对象的 CallAdapter、用来创建网络请求 CallCall.Factory、用来进行数据解析的数据转换器 Converter 以及用来构建网络请求 RequestRequestFactory 等实例对象。

构建完 HttpServiceMethod 实例对象后,调用其 invoke() 方法并传入网络请求接口的参数,在其 invoke() 方法中首先将前面配置好的 RequestFactoryCall.FactoryConverter 以及输入的网络请求接口的参数构建 OkHttpCall 实例对象,然后将构建的 OkHttpCall 实例对象作为入参传给 RxJava2CallAdapter.adapt() 方法进行下一步的处理。

3.6 OkHttpCall

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;
  
  OkHttpCall(RequestFactory requestFactory, Object[] args,
      okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {
    this.requestFactory = requestFactory;    // 网络请求 RequestFactory 工厂 
    this.args = args;    // 网络请求接口的参数
    this.callFactory = callFactory;	   // 网络请求 Call 工厂
    this.responseConverter = responseConverter;	   // 数据转换器
  }
}

OkHttpCallRetrofit 库中接口 Call 的一个实现类,其入参就是前面配置好的网络请求会用到的一些资源,实现了接口 Call 的几个重要方法:

  • execute():表示同步请求,返回值就是网络请求结果;
  • enqueue(Callback<T> callback):表示异步请求,返回值需要通过 Callback 回调来获取;
  • request():表示创建一个请求,返回 Request 类型。

3.7 RxJava2CallAdapter.adapt()

final class RxJava2CallAdapter implements CallAdapter<Object> {
  private final Type responseType;
  
  @Override public Type responseType() {
    return responseType;
  }
  
  @Override public <R> Object adapt(Call<R> call) {
  	// 使用入参 OkHttpCall 对象构建 CallObservable 实例对象,后续根据不同的条件新建或转换为符合要求的 Observable
    Observable<Response<R>> responseObservable = new CallObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) { // 参考 2.6.1 RxJava2CallAdapterFactory.create()的分析,isBody 为 true
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) { // 如果设置了 scheduler 则需建立订阅关系
      observable = observable.subscribeOn(scheduler);
    }

	// Flowable 能够发射0或n个数据,并以成功或者错误事件终止。支持背压,可以控制数据源发射的速度
    if (isFlowable) { // 如果是 Flowable,则将 Observable 转换为 Flowable
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) { // 如果是 Single,则将 Observable 转换为 Single,Single 只发射单个数据或者错误事件
      return observable.singleOrError();
    }
    // Maybe 能够发射0或者1个数据,要么成功,要么失败。有点类似于 Optional
    if (isMaybe) { // 如果是 Maybe,则将 Observable 转换为 Maybe
      return observable.singleElement();
    }
    // Completable 从来不发射数据,只处理onComplete和onError事件。可以看成 Rx 的 Runnable
    if (isCompletable) { // 如果是 Completable,则将 Observable 转换为 Completable
      return observable.ignoreElements();
    }
    return observable;
  }
}

RxJava2CallAdapter.adapt() 方法经过判断处理得到所需的可以操作的 Observable 网络请求对象,由于这里只是简单的使用,没有特殊要求的情况下返回的是 BodyObservable 对象。

问题:为什么 InvocationHandler.invoke() 方法不可以直接返回 OKHttpCall 对象,而是调用 CallAdapter.adapt(call, args) 方法进行适配器适配?
答:想象一下,如果没有适配器的话,网络请求返回接口只能直接返回 OkHttpCall,且所有的网络请求都是用 OkHttpCall 进行,这样就失去了 Retrofit 封装的意义,也不够灵活,如:RxJavaObservable 就无法支持。而采用适配器模式,将网络请求的核心类 OkHttpCall 进行适配,可根据实际需要通过适配器的适配返回适配后的对象,使得用户在使用 Retrofit 的时候可以自定义想要的返回类型。

小结

Retrofit 采用了外观模式统一调用创建网络请求接口实例和网络请求参数配置的方法,具体细节是:

  • 通过动态代理模式来动态的创建网络请求接口的实例对象 HttpServiceMethod
  • 通过 Retrofit.loadServiceMethod() 方法从 serviceMethodCache 缓存队列中获取 HttpServiceMethod 实例对象,如缓存中已有对应的实例对象,则直接返回(缓存机制,避免重复解析创建);
  • 如果缓存中没有则由 ServiceMethod.parseAnnotations() 解析注解获得,通过解析网络请求接口方法的参数、返回值类型和注解,从 Retrofit 对象中获取对应的网络请求的 URL 地址、网络请求执行器、网络请求适配器及数据转换器(策略模式);
  • 构建 HttpServiceMethod 实例对象,保存前面解析获取到的网络请求所需的必要信息,并把新建的 HttpServiceMethod 实例对象添加到 serviceMethodCache 缓存队列中;
  • 调用 HttpServiceMethod.invoke() 方法,通过适配的 RxJava2CallAdapter.adapt() 方法,传入新建的 OkHttpCall 实例对象,最终创建并返回一个 Observable 类型的网络请求对象 BodyObservable

4. Retrofit 执行网络请求

经过前面几节的分析,Retrofit 实例对象和 Observable 类型的网络请求对象都已创建完,那怎么来执行网络请求呢?

接下来为了更好的理解 Retrofit 的网络请求执行流程,对 Retrofit 进行了简单的封装以便于更好的理解其与 RxJava 的结合使用,示例代码如下:

RetrofitManager.getInstance()	// 获取 Retrofit 实例对象
		.getNetService(Api.class)	// 内部通过 Retrofit.create() 方法创建网络请求接口的实例对象
		.getUserInfo()	// 通过网络请求接口的实例对象,对请求的参数等信息进行封装,生成最终的网络请求对象 Observable<UserInfoBean>
		.subscribeOn(Schedulers.io())	// 指定被观察者 Observable 是在 Schedulers.io() 线程执行操作
		.observeOn(AndroidSchedulers.mainThread()) // 指定观察者 Observer在 AndroidSchedulers.mainThread(),即 Android主线程上执行操作,以更新UI
		.subscribe(new Observer<UserInfoBean>() { // 构建观察者 Observer 实例对象,通过 subscribe() 完成订阅,此时被观察者 Observable 开始向观察者发送数据
			@Override
			public void onSubscribe(Disposable d) { // 订阅时的操作 }

			@Override
			public void onNext(UserInfoBean userInfo) {
				// UI界面展示获取到的用户信息
			}

			@Override
            public void onError(Throwable e) { // 出错时的操作 }

			@Override
			public void onComplete() { // 完成时的操作 }
		});

被观察者 Observable 和观察者 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer

4.1 Observable.subscribe()

public abstract class Observable<T> implements ObservableSource<T> {
    @SchedulerSupport(SchedulerSupport.NONE)
    @Override
    public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
        	// RxJava 提供的一个钩子方法,用于在 Observable 被订阅时进行一些自定义的逻辑处理
        	// 你可以通过实现该方法来拦截所有的 subscribe 调用,并对其进行相应的处理
            observer = RxJavaPlugins.onSubscribe(this, observer);

            ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
			// 继续调用 subscribeActual()
            subscribeActual(observer);
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            // can't call onError because no way to know if a Disposable has been set or not
            // can't call onSubscribe because the call might have set a Subscription already
            RxJavaPlugins.onError(e);

            NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
            npe.initCause(e);
            throw npe;
        }
    }
}

Observable.subscribe() 方法中继续调用其 subscribeActual() 方法,看名字应该是真正用来订阅的,但其实这是一个抽象方法,在前面获取到的 BodyObservable 继承自 Observable 并实现了该方法。

4.2 BodyObservable.subscribeActual()

final class BodyObservable<T> extends Observable<T> {
  private final Observable<Response<T>> upstream;
  // 创建 BodyObservable 时传入的是 CallObservable 实例对象
  BodyObservable(Observable<Response<T>> upstream) {
    this.upstream = upstream;
  }
  
  @Override protected void subscribeActual(Observer<? super T> observer) {
  	// 这里转调 CallObservable.subscribe() 方法
    upstream.subscribe(new BodyObserver<>(observer));
  }

BodyObservable.subscribeActual() 方法继续转调 CallObservable.subscribe() 方法,CallObservable 本身没有 subscribe() 方法,因此调用的是其父类 Observable.subscribe() 方法,最后流程转调到 CallObservable.subscribeActual() 方法。

4.3 CallObservable.subscribeActual()

final class CallObservable<T> extends Observable<Response<T>> {
  private final Call<T> originalCall;
  CallObservable(Call<T> originalCall) {
    this.originalCall = originalCall;
  }
  
  @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
    // 为每个新的观察者克隆 originalCall 的副本
    Call<T> call = originalCall.clone();
    observer.onSubscribe(new CallDisposable(call)); // 开始执行onSubscribe方法

    boolean terminated = false;
    try {
      // 请求开始执行,会进行阻塞
      Response<T> response = call.execute();
      if (!call.isCanceled()) { // 请求未被取消,拿到数据之后,执行onNext()方法发送数据
        observer.onNext(response);
      }
      if (!call.isCanceled()) { // 未被取消,则执行完成
        terminated = true;
        observer.onComplete();
      }
    } catch (Throwable t) {
      Exceptions.throwIfFatal(t);
      if (terminated) { 
        RxJavaPlugins.onError(t); // 执行异常方法
      } else if (!call.isCanceled()) {
        try {
          observer.onError(t);
        } catch (Throwable inner) {
          Exceptions.throwIfFatal(inner);
          RxJavaPlugins.onError(new CompositeException(t, inner));
        }
      }
    }
  }
}

CallObservable.subscribeActual() 方法的执行流程如下:

  • 通过 call.execute() 方法执行请求,此处 Call 是在执行 RxJava2CallAdapter.adapt() 方法时传进来的。因此这里调用的是 Call 的实现类 OkHttpCall.execute() 方法;
  • 请求未取消,且成功拿到数据之后,执行 Observer.onNext() 方法向观察者发送数据,即 UI 界面获取到数据并展示获取到的信息。

4.4 OkHttpCall.execute()

final class OkHttpCall<T> implements Call<T> {
  @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 Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) { // 加锁处理,防止重复执行当前请求
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      if (creationFailure != null) { // 创建 RealCall 失败,出现了异常,进行处理
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else if (creationFailure instanceof RuntimeException) {
          throw (RuntimeException) creationFailure;
        } else {
          throw (Error) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) { // 第一次执行时为null
        try {
          call = rawCall = createRawCall(); // 创建一个 RealCall
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
	// 执行网络请求并解析响应
    return parseResponse(call.execute());
  }
  
  private okhttp3.Call createRawCall() throws IOException {
  	// 这里 callFactory 就是之前 Retrofit 初始化时添加的 OkHttpClient
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }
}

OkHttpCall.execute() 方法中,首先调用 createRawCall() 方法创建一个 RealCall,随后调用 RealCall.execute() 方法执行网络请求,最后调用 parseResponse() 方法解析网络请求响应。

4.4.1 RequestFactory.create()
final class RequestFactory {
  private final ParameterHandler<?>[] parameterHandlers;
  ......
  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 + ")");
    }
	// 使用构建 RequestFactory 实例时保存的网络请求所需的必要参数来构建 RequestBuilder 实例对象
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,
        headers, contentType, hasBody, isFormEncoded, isMultipart);
	// 对网络请求接口方法中的每个参数利用对应的 ParameterHandler 进行解析
    List<Object> argumentList = new ArrayList<>(argumentCount);
    for (int p = 0; p < argumentCount; p++) {
      argumentList.add(args[p]);
      handlers[p].apply(requestBuilder, args[p]);
    }
	// 最后通过 RequestBuilder 建造者模式构建 Request 实例对象
    return requestBuilder.get()
        .tag(Invocation.class, new Invocation(method, argumentList))
        .build();
  }
}

RequestFactory.create() 方法首先使用构建 RequestFactory 实例时保存的网络请求所需的必要参数来构建 RequestBuilder 实例对象,随后通过 RequestBuilder 建造者模式构建 Request 实例对象。

4.4.2 OkHttpClient.newCall()
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
	......
    public Call newCall(Request request) {
        return RealCall.newRealCall(this, request, false);
    }
}

OkHttpClient.newCall() 方法继续调用 RealCall.newRealCall() 方法创建 RealCall 实例对象并返回。

4.4.3 RealCall.newRealCall()
final class RealCall implements Call {
    final OkHttpClient client;
    private Transmitter transmitter;
    final Request originalRequest;
    final boolean forWebSocket;
    private boolean executed;
    
    private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
        this.client = client;
        this.originalRequest = originalRequest;
        this.forWebSocket = forWebSocket;
    }
    
    static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
        RealCall call = new RealCall(client, originalRequest, forWebSocket);
        call.transmitter = new Transmitter(client, call);
        return call;
    }
}

RealCallOkHttp 库中 Call 的实现类,实现了 Call 接口内部定义的同步与异步请求、取消请求等方法。在 RealCall.newRealCall() 方法中,首先根据入参创建 RealCall 实例对象,然后使用新建的 RealCallOkHttpClient 自身来新建 Transmitter 实例对象并赋值给 RealCall.transmitter 成员变量,最后返回刚创建的 RealCall 实例对象。

OkHttp 后面的代码本文不再深入,后续写文章深入剖析,现在已经获取到 RealCall 实例对象,并调用 RealCall.execute() 方法,后续会通过 RealCall 的拦截器链层层调用后,再一步步返回请求响应 Response,也就是说现在已经获取到网络请求返回的 Response,接下来分析 Retrofit 是如何解析请求响应的。

4.5 OkHttpCall.parseResponse()

final class OkHttpCall<T> implements Call<T> {
  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.
    // 移除 Response 的响应体 ResponseBody(唯一有状态的对象),这样我们就可以传递响应
    rawResponse = rawResponse.newBuilder()
    	// Response 设置没有内容的 NoContentResponseBody
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code(); // 响应码
    if (code < 200 || code >= 300) { // 响应异常情况
      try {
        // 缓冲整个主体以避免将来的 I/O 操作
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse); // 将请求异常的情况进行返回
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) { // 请求成功情况,只是返回数据为null
      rawBody.close();
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      // 转换器 Converter 转换 Response 的 ResponseBody
      T body = responseConverter.convert(catchingBody);
      // 调用 Response.success() 方法构建一个新的 Response 并返回 
      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;
    }
  }
}

OkHttpCall.parseResponse() 方法首先获取 ResponseResponseBody 响应体,调用 responseConverter.convert() 方法对 ResponseBody 响应体进行数据转换,最后调用 Response.success() 方法构建一个新的 Response 并返回。

4.5.1 GsonResponseBodyConverter.convert()
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  // 用于数据解析的主要类,内部采用工厂设计模式来实现不同 TypeAdapter 的创建,其成员变量fatories保存了
  // TypeAdapterFactory 列表,成员函数 getAdapter(type) 方法则根据不同的 type 去匹配 factories 中的一个工厂类,
  // 然后调用该工厂类的 create() 方法得到一个相应的 TypeAdapter 对象
  private final Gson gson;
  private final TypeAdapter<T> adapter;	 // TypeAdapter是一个抽象类,定义了转换的顶层接口,具体功能是在其子类中实现的

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

  @Override public T convert(ResponseBody value) throws IOException {
  	// 通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      // TypeAdapter.read() 方法将 Json 数据流解析成结构化对象T,其内部是通过 fromJson()方法
      // 此处 adapter 是 GsonConverterFactory.responseBodyConverter() 方法中由 Gson.getAdapter()方法获取的
      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();
    }
  }
}

GsonResponseBodyConverter 类在前面分析过,在其实现的 convert() 方法中,首先通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入,然后通过 TypeAdapter.read() 方法将 Json 数据流解析成结构化对象 T 并返回,其内部是通过 fromJson()方法实现的。

4.5.2 Gson.getAdapter()
public final class Gson {
  @SuppressWarnings("unchecked")
  public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
  	// 获取 Map<TypeToken<?>, TypeAdapter<?>> 缓存中的请求 adapter 是否存在,存在即返回 
    TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
    if (cached != null) {
      return (TypeAdapter<T>) cached;
    }
	// 本地线程缓冲中获取当前线程的请求数据信息
    Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
    boolean requiresThreadLocalCleanup = false; // 是否清除本地线程缓冲数据
    if (threadCalls == null) { // 本地线程缓冲中不存在
      threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>(); // 实例化一个 HashMap
      calls.set(threadCalls); // 缓存至 TLB 中
      requiresThreadLocalCleanup = true; // 进行清除
    }

    // 键和值类型参数始终一致
    FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type); // 获取当前返回类型的FutureTypeAdapter适配器
    if (ongoingCall != null) {
      // 已经存在当前返回值的适配器则直接返回
      return ongoingCall;
    }

    try { // 当前 FutureTypeAdapter 适配器依旧为null,创建一个适配器
      FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
      threadCalls.put(type, call); // 并将当前适配器与对应的 type 保存到 HashMap 中
	  // 在 Gson 初始化的 List<TypeAdapterFactory> 中遍历查找对应的 TypeAdapter
      for (TypeAdapterFactory factory : factories) {
        // 获取到解析适配器
        TypeAdapter<T> candidate = factory.create(this, type);
        if (candidate != null) {
          call.setDelegate(candidate); // 设置参数
          typeTokenCache.put(type, candidate); // 存入缓存 Map<TypeToken<?>, TypeAdapter<?>> 集合中
          return candidate;
        }
      }
      throw new IllegalArgumentException("GSON cannot handle " + type);
    } finally {
      threadCalls.remove(type);

      if (requiresThreadLocalCleanup) {
        calls.remove();
      }
    }
  }
}

Gson.getAdapter() 方法查找并获取指定类型映射的 TypeAdapter 实例对象,TypeAdapter 是一个抽象类,其 read() 方法在不同子类中实现的方式也不一样,这里以 ReflectiveTypeAdapterFactory 类的内部类 Adapter 为例,其继承自 TypeAdapter 类并实现其 read() 方法。

4.5.3 ReflectiveTypeAdapterFactory.Adapter.read()
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
  ......
  public static final class Adapter<T> extends TypeAdapter<T> {
    private final ObjectConstructor<T> constructor;
    private final Map<String, BoundField> boundFields;
    
    @Override public T read(JsonReader in) throws IOException {
      if (in.peek() == JsonToken.NULL) { // 得到 JsonToken.NULL 则不进入当前判断
        in.nextNull();
        return null;
      }
      T instance = constructor.construct(); // 初始化实例操作
      try {
        in.beginObject(); // 开始解析对象
        while (in.hasNext()) { // 是否有下一个,第一次到这里,返回 PEEKED_DOUBLE_QUOTED_NAME true
          String name = in.nextName();  // 获取 name 信息
          BoundField field = boundFields.get(name);  // 根据集合去获取里面的字段信息
          if (field == null || !field.deserialized) { // 如果字段为 null 或字段不能反序列化
            in.skipValue(); // 跳过value值,因为解析的类对象中不存在当前字段或者这个字段不能反序列化
          } else {
            field.read(in, instance); // 开始执行,根据字段类型去读取 value 值
          }
        }
      } catch (IllegalStateException e) {
        throw new JsonSyntaxException(e);
      } catch (IllegalAccessException e) {
        throw new AssertionError(e);
      }
      in.endObject();
      return instance;
    }
  }
}

限于篇幅 Retrofit 后续解析过程本文不再继续深入,在通过数据转换器 GsonResponseBodyConverter.convert() 方法对 ResponseBody 响应体进行数据解析转换后,最后会调用 Response.success() 方法构建一个新的 Response 并返回。

4.6 Response.success()

public final class Response<T> {
  // 由 rawResponse 和 body 创建一个成功的 Response 作为反序列化的 body
  public static <T> Response<T> success(@Nullable T body, okhttp3.Response rawResponse) {
    checkNotNull(rawResponse, "rawResponse == null");
    if (!rawResponse.isSuccessful()) {
      throw new IllegalArgumentException("rawResponse must be successful response");
    }
    // 判空并检查是成功的,则重新构建 okhttp3.Response 响应
    return new Response<>(rawResponse, body, null);
  }
}

Response.success() 方法中,由 rawResponsebody 创建一个成功的 Response 响应作为反序列化的 body 并返回。

此时,回到 4.3 CallObservable.subscribeActual() 方法,如果请求未取消,且成功拿到数据之后,执行 Observer.onNext() 方法向观察者发送数据,即 UI 界面获取到数据并展示获取到的信息。流程至此,Retrofit 的请求及解析过程也剖析完毕,当然里面还有很多细节,在一篇文章中是很难剖析完全的,感兴趣的可以再深入跟一下,后续有时间,笔者也会继续剖析。

小结

Retrofit 结合 RxJava 来实现网络请求是目前比较常见的异步编程模式,可以提高网络请求的效率和响应速度。

  • Retrofit 创建 Observable 网络请求对象后,使用该对象发送网络请求的结果;
  • Retrofit 使用 OkHttpRequest 发送网络请求,网络请求最终是通过 OkHttp 内部的 RealCall 来执行,经过其拦截器链层层调用后,再一步步返回请求响应 Response
  • Retrofit 对返回的数据使用创建 Retrofit 实例时设置的数据转换器工厂 GsonConverterFactory 所构建的 GsonResponseBodyConverter 解析返回的数据,最终得到一个 Response 对象;
  • 通过 RxJava 的 subscribe() 方法为 Observable 订阅观察者 Observer,接收并处理网络请求的返回值;
  • 通过 RxJava 提供的线程调度器,可以方便的切换线程,实现在不同的线程中执行网络请求和 UI 操作。

总结

Retrofit 本质上是一个 RESTfulHttp 网络请求框架的封装,通过大量的设计模式封装了 OkHttp,使得网络请求更加简洁易用。

  • 创建 Retrofit 实例,通过 Retrofit 内部类 Builder 构建实例对象,并配置网络请求所需的各种参数及适配器工厂等;
  • 创建网络请求接口的实例,RetrofitHttp 请求抽象成 Java 接口,在接口里用注解描述和配置网络请求参数;
  • Retrofit 采用外观模式统一调用创建网络请求接口实例和网络请求参数配置的方法:
    • 动态创建网络请求接口的实例(通过 InvocationHandler 对象的 invoke() 方法统一进行拦截处理);
    • 创建 ServiceMethod 对象,并对 ServiceMethod 对象进行网络请求参数配置:网络请求接口方法的参数、返回值和注解等;
    • 创建并返回 OkHttpCall 类型的网络请求对象,然后通过适配的 RxJava2CallAdapter.adapt() 方法,返回适配后的 Observable 类型的网络请求对象 BodyObservable
  • Retrofit 使用 OkHttpRequest 发送网络请求,网络请求最终是通过 OkHttp 内部的 RealCall 来执行,经过其拦截器链层层调用后,再一步步返回请求响应 Response
  • Retrofit 对返回的数据使用创建 Retrofit 实例时设置的数据转换器工厂 GsonConverterFactory 所构建的 GsonResponseBodyConverter 解析返回的数据,最终得到一个 Response 对象;
  • 通过 RxJava 的 subscribe() 方法为 Observable 订阅观察者 Observer,接收并处理网络请求的返回值;
  • 最后,通过 RxJava 提供的线程调度器,可以方便的切换线程,实现在不同的线程中执行网络请求和 UI 操作。

参考

  • square/Retrofit:github.com/square/retrofit
  • square/okhttp:github.com/square/okhttp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1871523.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows的内核对象

内核对象句柄特定于进程。 也就是说,进程必须创建 对象或打开现有对象以获取内核对象句柄。 内核句柄上的每个进程限制为 2^24。 但是,句柄存储在分页池中,因此可以创建的实际句柄数取决于可用内存。 可以在 32 位 Windows 上创建的句柄数明显低于 2^24。 任何进程都可以为…

Golang | Leetcode Golang题解之第201题数字范围按位与

题目&#xff1a; 题解&#xff1a; func rangeBitwiseAnd(m int, n int) int {for m < n {n & (n - 1)}return n }

Linux技能篇-恢复lvm物理卷

项目场景&#xff1a; 今天遇到一个很有意思的故障&#xff0c;我用虚拟机来还原了当前的故障场景。 首先来看&#xff0c;系统中只有一个lvn卷组 我们给系统中添加一块磁盘&#xff0c;使用pvcreate创建物理卷 pvcreate /dev/sdb并将容量添加到当前的卷组中 创建一个lvm逻辑…

基于Spring Boot医护人员排班系统

设计技术&#xff1a; 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatisvue 工具&#xff1a;IDEA、Maven、Navicat 主要功能&#xff1a; 医护类型管理 医护人员排班系统的系统管理员可以对医护类型添加修改删除以及查询操作。具体界面…

Opencv学习项目7——face_recognition

前面两篇博客解决了安装dlib库的问题和numpy和dlib不兼容的问题&#xff0c;今天开始做人脸识别第一个项目 我们可以从网上下载一张带有人脸的图片或者自己电脑有的也可以&#xff0c;我这里使用lyf的图片进行演示 加载图像文件 img1 face_recognition.load_image_file(lyf1.…

mac菜单栏应用管理软件:Bartender 4 for Mac 中文激活版

Bartender 4 是一款由Bearded Men Games开发的适用于Mac操作系统的应用程序&#xff0c;它被设计用来优化和美化Mac菜单栏的功能。自从macOS Big Sur开始&#xff0c;Mac的菜单栏可以自定义&#xff0c;用户可以添加和移除各种图标。Bartender 4就是在这个背景下应运而生&#…

论文阅读Vlogger: Make Your Dream A Vlog

摘要 论文介绍了一个名为“Vlogger”的通用人工智能系统&#xff0c;它能够根据用户的描述生成分钟级的视频博客&#xff08;vlog&#xff09;。与通常只有几秒钟的短视频不同&#xff0c;vlog通常包含复杂的故事情节和多样化的场景&#xff0c;这对现有的视频生成方法来说是一…

CPPTest设计分析

目录 1 概述2 设计3 扩展Output3.1 扩展实例 1 概述 CppTest是一个可移植、功能强大但简单的单元测试框架&#xff0c;用于处理C中的自动化测试。重点在于可用性和可扩展性。支持多种输出格式&#xff0c;并且可以轻松添加新的输出格式。 CppTest下载地址Sourceforge Github地…

django学习入门系列之第三点《伪类简单了解》

文章目录 hover&#xff08;伪类&#xff09;after&#xff08;伪类&#xff09;往期回顾 hover&#xff08;伪类&#xff09; 伪类指的是用冒号加的 hover样式指的是&#xff0c;当用户光标移动到设定区域后&#xff0c;所执行的用法 如&#xff1a; <!DOCTYPE html>…

视频网站系统

摘 要 随着互联网的快速发展和人们对视频内容的需求增加&#xff0c;视频网站成为了人们获取信息和娱乐的重要平台。本论文基于SpringBoot框架&#xff0c;设计与实现了一个视频网站系统。首先&#xff0c;通过对国内外视频网站发展现状的调研&#xff0c;分析了视频网站的背景…

静态资源服务器

上一章【认识 MIME 和 HTTP】。 我们认识和了解了 MIME 的概念和作用&#xff0c;也简单地学习了通过浏览器控制台查看请求和返回的用法。 通过对不同的 HTML、CSS、JS 文件进行判断&#xff0c;设置不同的 MIME 值&#xff0c;得以让我们的浏览器正正确地接收和显示不同的文…

2-18 基于matlab的关于联合对角化盲源分离算法的二阶盲识别(SOBI)算法

基于matlab的关于联合对角化盲源分离算法的二阶盲识别&#xff08;SOBI&#xff09;算法。通过联合对角化逼近解混矩阵。构建的四组信号&#xff0c;并通过认为设置添加噪声比例&#xff0c;掩盖信号信息。通过SOBI算法实现了解混。程序已调通&#xff0c;可直接运行。 2-18联合…

技术速递|Visual Studio Code 的 .NET MAUI 扩展现已正式发布

作者&#xff1a;Maddy Montaquila 排版&#xff1a;Alan Wang 今天&#xff0c;我们非常高兴地宣布 .NET MAUI VS Code 扩展插件结束了预览阶段&#xff0c;并将包含一些期待已久的新功能 - 包括 XAML IntelliSense 和 Hot Reload&#xff01; 什么是 .NET MAUI 扩展插件&…

成功解决​​​​​​​TypeError: __call__() got an unexpected keyword argument ‘first_int‘

成功解决TypeError: __call__() got an unexpected keyword argument first_int 目录 解决问题 解决思路 解决方法 T1、直接调用原始函数 T2、检查装饰器实现 T3、使用不同的调用方式 解决问题 result = multiply(**arguments) File "D:\ProgramData\Anaconda3\Li…

BFS:队列+树的宽搜

一、二叉树的层序遍历 . - 力扣&#xff08;LeetCode&#xff09; 该题的层序遍历和以往不同的是需要一层一层去遍历&#xff0c;每一次while循环都要知道在队列中节点的个数&#xff0c;然后用一个for循环将该层节点走完了再走下一层 class Solution { public:vector<vec…

【教程】简介nccl-test工具

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ GitHub - NVIDIA/nccl-tests: NCCL TestsNCCL Tests. Contribute to NVIDIA/nccl-tests development by creating an account on GitHub.https://githu…

Unity3D 物体的运动

运动方式1 修改 position / localPosition &#xff0c;可以让物体运动 例如&#xff0c; Vector3 pos this.transform.localPosition; pos.z distance; this.transform.localPosition pos; 此时&#xff0c;小车向Z 方向运动 具体代码如下 using System.Collection…

[C#]基于opencvsharp实现15关键点人体姿态估计

数据集 正确选择数据集以对结果产生适当影响也是非常必要的。在此姿势检测中&#xff0c;模型在两个不同的数据集即COCO关键点数据集和MPII人类姿势数据集上进行了预训练。 1. COCO&#xff1a;COCO关键点数据集是一个多人2D姿势估计数据集&#xff0c;其中包含从Flickr收集的…

matlab绘制二维曲线,如何设置线型、颜色、标记点类型、如何设置坐标轴、matlab 图表标注、在图中标记想要的点

matlab绘制二维曲线&#xff0c;如何设置线型、颜色、标记点类型、如何设置坐标轴、matlab 图表如何标注、如何在图中标记想要的点 matlab绘制二维曲线&#xff0c;如何在图中标记想要的点。。。如何设置线型、颜色、标记点类型。。。如何设置坐标轴。。。matlab 图表标注操作…