yunshuipiao/Potato

retrofit2

yunshuipiao opened this issue · 0 comments

Retrofit

A type-safe HTTP client for Android and Java

基于 version 2.5.0 进行分析。

Demo

官方使用文档

Retrofit 将 Http API 转换为 java 接口,因此可以做如下定义

public interface GitHubService {
  // 请求方法和地址
  @GET("users/{user}/repos")
  // 参数和返回值定义
  Call<List<Repo>> listRepos(@Path("user") String user);
}

生成 上述接口的实现类。

// 实例化 retrofit
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();
// 创建接口实现
GitHubService service = retrofit.create(GitHubService.class);

发起异步请求,之后交给 okhttp 来做底层处理,回到之前对 okhttp 请求过程的分析。

Call<List<Repo>> repos = service.listRepos("octocat");

下面就针对每一部分进行源码分析。

Retrofit

首先对 retrofit 实例的创建,用的是建造者模式。这里直接看最后的 build() 过程,直接了解配置了什么参数。

public Retrofit build() {
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }
	
  // okhttp call 创建工厂,工厂模式的体现。
  // 将类实例化操作和使用对像的操作分开
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    // okhttp 对象,用于创建 call
    callFactory = new OkHttpClient();
  }
	
  // 异步执行时进行回调
  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }

  // Make a defensive copy of the adapters and add the default Call adapter.
  // call 调用适配器,使得返回接口定义的返回值
  List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

  // Make a defensive copy of the converters.
  // 序列和反序列化转换器
  List<Converter.Factory> converterFactories = new ArrayList<>(
      1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

  // Add the built-in converter factory first. This prevents overriding its behavior but also
  // ensures correct behavior when using converters that consume all types.
  // 所有的转换器
  converterFactories.add(new BuiltInConverters());
  converterFactories.addAll(this.converterFactories);
  converterFactories.addAll(platform.defaultConverterFactories());
	
  return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
      unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

interface

接着就可以实现之前声明的接口。

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
// 最重要的部分
public <T> T create(final Class<T> service) {
  // 判断是接口并且不能继承其他接口
  Utils.validateServiceInterface(service);
  if (validateEagerly) {
    // 提前对 service 中的方法注解进行合法性验证
    eagerlyValidateMethods(service);
  }
  // 使用动态代理生成对应的 Service 
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
      // 处理被代理对象的某个方法发生是调用,比如这里的 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) {
            return method.invoke(this, args);
          }
          if (platform.isDefaultMethod(method)) {
            return platform.invokeDefaultMethod(method, service, proxy, args);
          }
          return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
        }
      });
}
	// 加载 Service 并返回正在使用的方法
  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;
  }

在上面的过程中,代理类解析方法的相关注解,包括 http 的请求方法, 地址,参数等信息,内容比较多,可以深入去看。下面就到了请求过程。

上次还提到动态代理, 当 service.listRepos("octocat") 时,接口中的调用会集中转发到 InvocationHandler 的 invoke() 方法,集中进行处理。

请求过程

当发生方法调用时,请求过程会来到如下代码:

@Override final @Nullable ReturnT invoke(Object[] args) {
  Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
  return adapt(call, args);
}

用相关的信息创建一个 okhttp 的 call 对象,

追下去就是 okhttp 的请求过程了。