Android-Retrofit源码分析

454 阅读4分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

介绍

Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。

image.png

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

网络请求的流程

image.png

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

几大角色的作用

角色作用备注
网络请求执行器(Call)创建HTTP网络请求 Retrofit默认为okhttp3.call
网络请求适配器(CallAdapter)网络请求执行器call的适配器,将默认的网络请求执行器OkHttpCall转换成适合不同平台调用的网络请求执行器 Retrofit支持Android,Rxjava,java8和Guava四个平台。
数据转换器(Converter)将返回数据解析成我们需要的数据类型 Retrofit支持XML,Gson,JSON,protobuf
回调执行器(CallBackExecutor)线程切换(子线程->主线程) 将最后okhttp的请求结果通过callbackExecutor使用Handler异步回调传回主线程

网络适配器作用的理解:

一开始Retrofit只打算利用Okhttpcall通过ExecutorCallbackCall切换线程,但是后来发现使用Rxjava更加方便(不需要handler来切换线程),想要实现Rxjava,那就得睡用RxjavaCallAdapterFactoryCallAdapter将Okhttp转换成Rxjava(Scheduler)。好处是用最小的代价兼容来更多的平台。

使用

Retrofit retrofit = new Retrofit.Builder()
                                 .baseUrl("http://fanyi.youdao.com/")                     .addConverterFactory(GsonConverterFactory.create())
                                 .build();

源码分析

public final class Retrofit {
  //网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象)
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
  //网络请求器的工厂
  final okhttp3.Call.Factory callFactory;
  //网络请求的url地址
  final HttpUrl baseUrl;
  //数据转换器工厂的集合
  final List<Converter.Factory> converterFactories;
  //网络请求适配器工厂的集合
  final List<CallAdapter.Factory> callAdapterFactories;
  //回调方法执行器
  final @Nullable Executor callbackExecutor;
  //标识位(是否提前对业务接口中的注解进行验证转换的标志位)
  final boolean validateEagerly;
  
  //构造函数
  Retrofit(
      okhttp3.Call.Factory callFactory,
      HttpUrl baseUrl,
      List<Converter.Factory> converterFactories,
      List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor,
      boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
}
  • serviceMethod:包含所有网络请求信息的对象
  • baseUrl:网络请求的url地址
  • callFactory:网络请求工厂
  • adapterFactories:网络请求适配器工厂的集合
  • converterFactories:数据转换器工厂的集合
  • callbackExecutor:回调方法执行器

builder类

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类中

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

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //
        : new Platform(true);
  } 
}
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);
    }
  }
}

切换线程的流程:

  1. 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象
  2. 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用MainThreadExecutor的execute()通过handler切换到主线程

baseUrl

public Builder baseUrl(String baseUrl) {
  Objects.requireNonNull(baseUrl, "baseUrl == null");
  return baseUrl(HttpUrl.get(baseUrl));
}

public Builder baseUrl(HttpUrl baseUrl) {
  Objects.requireNonNull(baseUrl, "baseUrl == null");
  //把url参数分割成几个路径
  List<String> pathSegments = baseUrl.pathSegments();
  //检测最后一个碎片来检查URL参数是不是以"/"结尾,如果不是则抛出异常
  if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
    throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
  }
  this.baseUrl = baseUrl;
  return this;
}

addConverterFactory(GsonConverterFactory.create())

public final class GsonConverterFactory extends Converter.Factory {

  public static GsonConverterFactory create() {
    //创建gson对象
    return create(new Gson());
  }

  @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;
  }
...
}

GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory

//将上面创建的GsonConverterFactory放入到 converterFactories数组
public Builder addConverterFactory(Converter.Factory factory) {
  converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
  return this;
}

用于创建一个含有Gson对象实例的GsonConverterFactory并放入到数据转换器工厂converterFactories里

build()

public Retrofit build() {
  //判断baseUrl
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }
  //配置网络请求执行器(callFactory)
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    callFactory = new OkHttpClient();
  }
  //配置回调方法执行器
  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }
  //配置网络请求适配器工厂
  List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  
 // 向该集合中添加了步骤2中创建的CallAdapter.Factory请求适配器(添加在集合器末尾) callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

 //配置数据转换器工厂
  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());
// 最终返回一个Retrofit的对象,并传入上述已经配置好的成员变量
  return new Retrofit(
      callFactory,
      baseUrl,
      unmodifiableList(converterFactories),
      unmodifiableList(callAdapterFactories),
      callbackExecutor,
      validateEagerly);
}

小结

Retrofit 使用建造者模式通过Builder类建立了一个Retrofit实例,具体创建细节是配置了:

  • 平台类型对象(Platform - Android)

  • 网络请求的url地址(baseUrl)

  • 网络请求工厂(callFactory)

    默认使用OkHttpCall

  • 网络请求适配器工厂的集合(adapterFactories)

    本质是配置了网络请求适配器工厂- 默认是ExecutorCallAdapterFactory

  • 数据转换器工厂的集合(converterFactories)

    本质是配置了数据转换器工厂

  • 回调方法执行器(callbackExecutor)

    默认回调方法执行器作用是:切换线程(子线程 - 主线程)

由于使用了建造者模式,所以开发者并不需要关心配置细节就可以创建好Retrofit实例。

在创建Retrofit对象时,你可以通过更多更灵活的方式去处理你的需求,如使用不同的Converter、使用不同的CallAdapter,这也就提供了你使用RxJava来调用Retrofit的可能。