Retrofit 源码解析

本文基于 Retrofit 2.5

Retrofit :改造
改造了什么呢?
把一个 Http 请求转化为一个 Java 接口的调用。

文章目录

  • 一、简单使用
  • 二、一次调用
    • 2.1 InvocationHandler.invoke()
      • 2.1.1 创建 ServiceMethod
        • 2.1.1.1 创建 requestFactory
        • 2.1.1.2 创建 callFactory
        • 2.1.1.3 创建 callAdapter
        • 2.1.1.4 创建 responseConverter
      • 2.1.2 执行 ServiceMethod 的 invoke 方法
        • 2.1.2.1 创建 OkHttpCall
        • 2.1.2.2 callAdapter.adapt()
      • 2.1.3 添加 GsonConverter
      • 2.1.4 添加 RxJava2CallAdapter
  • 三、整体流程
  • 四、一些问题
  • 五、借鉴学习
    • 5.1 动态生成接口的实现类
    • 5.2 工厂模式

一、简单使用

这是官网给的例子(http://square.github.io/retrofit/)。

定义 Service 接口,该接口内的方法就是 api 调用。

public interface GithubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

创建 Retrofit 对象,并通过 Retrofit 对象再创建 Service 接口实现类的对象。

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GithubService githubService = retrofit.create(GithubService.class);

调用 Serice 对象的方法,发起网络请求。

Call<List<Repo>> repos = githubService.listRepos("gdeeer");

二、一次调用

从这句开始。

Call<List<Repo>> repos = githubService.listRepos("gdeeer");

点进去,发现找不到 listRepos 的实现。因为 githubService 的类是动态生成的,我们看不到类的实现。

只能去看下生成 githubService 对象的代码。

GithubService githubService = retrofit.create(GithubService.class);

2.1 InvocationHandler.invoke()

看 Retrofit 的 create() 方法。

public <T> T create(final Class<T> service) {
  ...
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
      new InvocationHandler() {
        ...
        @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
            throws Throwable {
          ...
          return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
        }
      });
}

可以看到,Retrofit 是通过 Proxy.newProxyInstance 来生成 GithubService 接口的实现类的,而接口内方法的处理逻辑就在 InvocationHandler 的 invoke() 中(更多关于Proxy.newProxyInstance 的内容可见Java 基础:静态代理和动态代理)。

invoke() 方法中执行了 loadServiceMethod(method).invoke(args)。所以 githubService.listRepos("gdeeer"); 方法的真正调用,就是在这里进行的。

2.1.1 创建 ServiceMethod

看一下 loadServiceMethod 方法。

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.parseAnnotations() 来新建,并放入缓存。

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    ...
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract T invoke(Object[] args);
}

ServiceMethod 是一个抽象类,只有一个方法 invoke(),ServiceMethod.parseAnnotations() 相当于一个工厂,用来创建 ServiceMethod 对象,它内部又调用了 HttpServiceMethod.parseAnnotations() 来创建。

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
  CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
  ...
  Converter<ResponseBody, ResponseT> responseConverter =
      createResponseConverter(retrofit, method, responseType);
  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}

终于出现了 new HttpServiceMethod(),HttpServiceMethod 是 ServiceMethod 的实现类,它接收4个参数:requestFactory、callFactory、callAdapter、responseConverter。

requestFactory 用来生成 okhttp3.Request,okhttp3.Request 代表一次 Http 请求。

callFactory 用来生成 okhttp3.Call,okhttp3.Call 代表一个准备好了的 Request。

callAdapter 用来处理 retrofit2.Call,retrofit2.Call 是 Retrofit 中定义的 Call,与 okhttp3.Call 基本一致,最终执行的还是 okhttp3.Call。

responseConverter 用来转化一个 response。

2.1.1.1 创建 requestFactory

ServiceMethod.parseAnnotations() 方法中会创建 requestFactory。

// ServiceMethod.java
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
  RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
  ...
}

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

通过 RequestFactory.Builder 来创建一个 RequestFactory。

2.1.1.2 创建 callFactory

HttpServiceMethod 的 parseAnnotations() 方法中会创建 callFactory。

创建方式是直接使用 Retrofit 类的 callFactory。

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...) {
  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  ...
}

Retrofit 中的 callFactory 在 Retrofit.Builder.build() 时初始化。没有指定的话,默认就是一个 OkHttpClient

// Retrofit#Builder.java
public Retrofit build() {
  ...
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    callFactory = new OkHttpClient();
  }
  ...
}

2.1.1.3 创建 callAdapter

HttpServiceMethod 的 parseAnnotations() 方法中会创建 callAdapter。

创建方式是通过 Retrofit 类,Retrofit 会遍历自己的 callAdapterFactories,找到合适的 CallAdaperFactory,如果找不到,会抛异常。

什么是合适的 CallAdaperFactory,就是能产生合适的 CallAdaper 的 Factory。什么是合适的 CallAdapter,就是能 Call 改编为指定的 returnType 的 CallAdapter。

CallAdapter 将 Call 改编(adapt into)为 T。

// HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...)(
	CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
	...
}

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(...) {
    ...
    return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    ...
}

// Retrofit.java
public CallAdapter<?, ?> callAdapter(...) {
  return nextCallAdapter(null, returnType, annotations);
}

public CallAdapter<?, ?> nextCallAdapter(...) {
  ...
  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;
    }
  }
  ...
}

Retrofit 中的 callAdapterFactories 在 Retrofit.Builder.build() 时初始化。

// Retrofit#Builder.java
public Retrofit build() {
  ...
  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }

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

初始化时,根据所在的不同平台,会添加不同的默认工厂。

  • Android 平台上,callbackExecutor 是 MainThreadExecutor。若当前机器的 Android 版本号大于 24,会添加 CompletableFutureCallAdapterFactory、ExecutorCallAdapterFactory。若小于等于 24,只添加一个 ExecutorCallAdapterFactory。

  • Java8 平台上,callbackExecutor 是 null。会添加 CompletableFutureCallAdapterFactory、 DefaultCallAdapterFactory。

DefaultCallAdapterFactory 只能生产 DefaultCallAdapter,它将 Call 改编为 Call(它自己)。

ExecutorCallAdapterFactory 只能生产 ExecutorCallAdapter,它将 Call 改编为 ExecutorCallbackCall(也是一个 Call)。

CompletableFutureCallAdapterFactory 只能生产 CompletableFutureCallAdapter(实际上是 BodyCallAdapter、ResponseCallAdapter),它将 Call 改编为 CompletableFuture

2.1.1.4 创建 responseConverter

HttpServiceMethod 的 parseAnnotations() 方法中会创建 callAdapter。

创建方式是通过 Retrofit 类,Retrofit 会遍历自己的 converterFactories,找到合适的 ConverterFactory,如果找不到,会抛异常。

什么是合适的 ConverterFactory,就是能生产合适的 Converter 的 Factory。什么是合适的 Converter,就是能将 ResponseBody 转化为指定 returnType 的 Converter。

Converter,将 F 转化为 T。(这里的 F,一般就是 ResponseBody)

// HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...) {
  ...
  Converter<ResponseBody, ResponseT> responseConverter =
    createResponseConverter(retrofit, method, responseType);
  ...
}

private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(...) {
  ...
  return retrofit.responseBodyConverter(responseType, annotations);
  ...
}

// Retrofit.java
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
  return nextResponseBodyConverter(null, type, annotations);
}

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(...) {
  ...
  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) {
      return (Converter<ResponseBody, T>) converter;
    }
  }
  ...
}

Retrofit 中的 converterFactories 在 Retrofit.Builder.build() 时初始化。

// Retrofit#Builder.java
public Retrofit build() {
  ...
  List<Converter.Factory> converterFactories = new ArrayList<>(
      1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

  converterFactories.add(new BuiltInConverters());
  converterFactories.addAll(this.converterFactories);
  converterFactories.addAll(platform.defaultConverterFactories());
  ...
}

初始化时,根据所在的不同平台,会添加不同的默认工厂。

  • Android 平台上,只会添加 BuiltInConverters。

  • Java8 平台上,会添加 BuiltInConverters、OptionalConverterFactory。

BuiltInConverters:

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

它只能生产可以将 ResponseBody 转化为:ResponseBodyVoidUnit 的 Converter,如果指定的 returnType 不是这几种,就会返回 null。

OptionalConverterFactory:

@Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
    Type type, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(type) != Optional.class) {
    return null;
  }

  Type innerType = getParameterUpperBound(0, (ParameterizedType) type);
  Converter<ResponseBody, Object> delegate =
      retrofit.responseBodyConverter(innerType, annotations);
  return new OptionalConverter<>(delegate);
}

它只能生产 OptionalConverter,它将 ResponseBody 转化为 Optional,如果指定的 returnType 不是 Optional,就会返回 null。

2.1.2 执行 ServiceMethod 的 invoke 方法

2.1.2.1 创建 OkHttpCall

获取到 HttpServiceMethod 对象后,就会调用它的 invoke 方法。

@Override ReturnT invoke(Object[] args) {
  return callAdapter.adapt(
      new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}

里面通过 requestFactory、callFactory、responseConverter 生成了一个 OkHttpCall 对象,CallAdapter 处理的就是它。

OkHttpCall 是 Retrofit2.Call 的实现类,它会包含一个 okhttp3.Call 的对象 rawCall,rawCall 通过 callFactory、requestFactory 创建。

okhttp3.Call rawCall = callFactory.newCall(requestFactory.create(args));

2.1.2.2 callAdapter.adapt()

接下来看 callAdapter 的 adapt() 方法。

adapt() 方法在 retrofit 包中,有四处实现。即包中定义了四个 CallAdapter,DefaultCallAdapter、ExecutorCallAdapter、BodyCallAdapter、ResponseCallAdapter。
在这里插入图片描述
DefaultCallAdapter 将 Call 改编为 Call。
ExecutorCallAdapter 将 Call 改编为 ExecutorCallbackCall(也是一个 Call)。
BodyCallAdapterResponseCallAdapter 将 Call 改编为 CompletableFuture(Java8 中的类)。

我们再回头看下最开始的代码。

Call<List<Repo>> repos = githubService.listRepos("gdeeer");

实际运行后,发生了异常。
Retrofit 源码解析_第1张图片
异常发生在 HttpServiceMethod.createResponseConverter() 方法中,即生产 Converter 的方法中。

如上面 2.1.1.4 中所说,生产 Converter 时,会遍历 Retrofit 中的 converterFactories,如果没有找到合适的 ConverterFactory,就会抛出异常。

默认的 converterFactories,只能生产 returnType 是 ResponseBodyVoidUnitOptional 的 converter。但我们的 listRepos() 方法的 returnType 是 Call>,所以它会返回 null。

2.1.3 添加 GsonConverter

系统内置的 ConverterFactory 不满足需求,我们只能自己创建新的 ConverterFactory。

官方文档上说,Retrofit 默认只支持将 HTPP bodies 转为 ResponseBody。如果要支持其他类型,需要使用新的 Converter,并提供了几种 Converter 库。
Retrofit 源码解析_第2张图片
我们使用 GsonConverter 来转化,引入 converter-gson 库后,修改 Retrofit 的 build 代码。

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

现在代码就可以正常运行了。

2.1.4 添加 RxJava2CallAdapter

implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'

RxJava2CallAdapter 将 Call 改编为一个 Observable。

Observable subscribe 时,会执行 Call,在 onNext 中回调。

三、整体流程

上面的目录已经很清楚,总结一下就是:

  1. 生成 ServiceMethod
  2. 调用 ServiceMethod.invoke
    1. 生成 CallAdapter、OkHttpCall
    2. 通过 CallAdapter 调用 OkHttpCall

四、一些问题

  • 为什么 HttpServiceMethod 的四个构造参数中,requestFactory 是在 ServiceMethod.parseAnnotations 时生成,而其他参数是在 HttpServiceMethod.parseAnnotations 时生成?

应该是开发者觉得以后还有除了 HttpServiceMethod 以外的 ServiceMethod 实现类,但是他们都需要 requestFactory,所以放在调用 HttpServiceMethod.parseAnnotations 之前生成。

  • 为什么 ServiceMethod 持有的对象,requestFactory、callFactory 使用的是 Factory,而 callAdatper、responseConverter 使用的 Factory 生产的产品?

因为 CallAdatper、ResponseConverter 对于每个方法来说,不管调用几次,它们的值都不变,但对于 Request、Call 来说,每次调用,都要产生不同的对象。

  • 为什么 Retrofit 要新定义一个 retrofit2.Call,而不直接使用 okhttp3.Call?为什么没有一个 retrofit2.Request?

实现 retrofit2.Call 接口的有两个类,一个是代理了 okhttp3.Call 的 OkHttpCall 类,另一个是代理了另一个 retrofit2.Call 的 ExecutorCallbackCall 类。

ExecutorCallbackCall 会把 retrofit2.Call 的 execute()、enqueue() 方法都放到 Executor 中执行。

  • RequestFactory、CallFactoty、CallAdapterFactory、ConverterFactory 都在哪里生成?他们的产品都在哪里生成(Factory 在哪里使用)?他们的产品在哪里使用?

RequestFactory 在 ServiceMethod.parseAnnotations 中生成。

Request 在 OkHttpCall.createRawCall 中生成并使用,用来生成 okhttp3.Call。

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

CallFactory 在 Retrofit.Builder.build() 方法中生成(即 OkHttpClient)。

Call 在 OkHttpCall.createRawCall 中生成并使用,用来生成 okhttp3.Call(会委托 OkHttpCall 调用它的方法)。OkHttpCall.createRawCall 在 OkHttpCall 执行方法时调用。

OkHttpCall 在 HttpServiceMethod.invoke 方法中生成。用户调用 api 方法后,获得 CallAdapter.adapt 生成的对象,再调用该对象的方法时使用。

CallAdapterFactory 在 Retrofit.Builder.build() 方法中生成。

CallAdapter 在 ServiceMethod.parseAnnotations 中生成,在用户调用 api 方法时使用。

ConverterFactory 在 Retrofit.Builder.build() 方法中生成。

Converter 在 ServiceMethod.parseAnnotations 中生成,在 OkHttpCall.executeOkHttpCall.enqueue 时使用。

五、借鉴学习

5.1 动态生成接口的实现类

5.2 工厂模式

你可能感兴趣的:(Retrofit,Android,Android,理解,Java,源码)