Retrofit源码分析

1. 序

基于retrofit 2.9.0

Retrofit并不是一个网络请求库,它主要是为了简化网络请求的构建和对返回数据的处理,网络请求是通过OkHttp实现的,而Retrofit仅负责网络请求接口的封装。在2.6.0版本之后,retrofit对kotlin协程进行了支持。

Retrofit的基本使用流程很简洁,为了实现这种简洁的使用流程,Retrofit内部使用了优秀的架构设计和大量的设计模式,它的源码非常值得我们一读。

2. 基本使用流程

  1. 定义API接口用于描述请求
    1
    2
    3
    4
    public interface GitHubService {
      @GET("users/{user}/repos")
      Call<List<Repo>> listRepos(@Path("user") String user);
    }
    
  2. 创建Retrofit并生成API的实现(注意:方法上面的注解表示请求的接口部分,返回类型是请求的返回值类型,方法的参数即是请求的参数)
1
2
3
4
5
6
7
8
// 1.构建Retrofit
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

// 2.创建网络请求接口实例
GitHubService service = retrofit.create(GitHubService.class);
  1. 调用API方法,生成Call,执行请求
1
2
3
4
5
6
//生成Call
Call<List<Repo>> repos = service.listRepos("octocat");
//同步执行请求
repos.execute()
//异步执行请求
repos.enqueue(Callback responseCallback)

阅读Retrofit源码前,需要对以下设计模式有所了解:

1
2
3
4
5
6
7
8
1.Retrofit构建过程 
建造者模式、工厂方法模式

2.创建网络请求接口实例过程
外观模式、代理模式、单例模式、策略模式、装饰模式(建造者模式)

3.生成并执行请求过程
适配器模式(代理模式、装饰模式)

同时需要对OkHttp源码有一定的了解,可以看上一篇OKHttp源码分析

3. 源码分析

按照上面的基本使用流程,我们来进行逐步分析内部是怎么实现的。

3.1 Retrofit构建过程

我们先来看看Retrofit内部结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public final class Retrofit {
   // 网络请求配置对象,存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等 
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
  ...

  public static final class Builder {
    // 平台类型对象(Platform -> Android)
    private final Platform platform;
    // 网络请求工厂,默认使用OkHttpCall(工厂方法模式)
    private @Nullable okhttp3.Call.Factory callFactory;
    // 网络请求的baseurl地址
    private @Nullable HttpUrl baseUrl;
    // 数据转换器工厂的集合
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    // 网络请求适配器工厂的集合,默认是ExecutorCallAdapterFactory
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    // 回调方法执行器,在 Android 上默认是封装了 handler 的 MainThreadExecutor, 默认作用是:切换线程(子线程 -> 主线程)
    private @Nullable Executor callbackExecutor;
    //是否要迫切的验证请求方法,开启则会马上加载所有方法。一般不用
    private boolean validateEagerly;

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

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

    ...

    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      //1.CallAdapter工厂集合
      // 这就是添加所有的adapter,这里用到的适配器模式,也就是从Okhttp的Call适配成Retrofit的Call
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      //添加默认的请求适配器 Android平台默认是DefaultCallAdapterFactory
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      //2.Converter工厂集合,有Gson、Moshi、Protobuf等
      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
      //添加默认的数据转换器
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }

  }
}

可以看到Retrofit中有一个全局变量serviceMethodCache,它是一个ConcurrentHashMap,内部以Method为键ServiceMethod为值,这个ServiceMethod就是我们之前定义的api接口中方法注解进行解析得到的。内部还有一个静态内部类Builder,通过建造者模式来构建需要不同配置的Retrofit实例,Builder在调用build()方法创建Retrofit对象时对很多配置进行了默认赋值。

我们看到builder内调用了Platform.get()方法,来看看它的实现:

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

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    //通过Dalvik虚拟机判断是否是android平台
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //创建Android的Platform
        : new Platform(true);//创建Java的Platform
  }
  ...
  //创建默认的CallAdapterFactory
  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }

  int defaultCallAdapterFactoriesSize() {
    return hasJava8Types ? 2 : 1;
  }
  //创建默认的ConverterFactory
  List<? extends Converter.Factory> defaultConverterFactories() {
    return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
  }

  ...

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

}

可以看到Platform内部针对Android和Java平台做了不同的实现。

3.2 创建GitHubService

我们来看GitHubService service = retrofit.create(GitHubService.class):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  public <T> T create(final Class<T> service) {
    //校验服务接口
    validateServiceInterface(service);
    //使用动态代理拿到请求接口所有注解配置后,创建网络请求接口实例
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable {
                //如果方法是object的方法正常调用
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method) //接口中的default方法
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);//一般方法使用该方法加载
              }
            });
  }

可以看到retrofit.create方法内部通过动态代理来创建了GitHubService的实例,在我们调用GitHubService中的方法时就会先执行InvocationHandler的invoke方法。

继续loadServiceMethod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Retrofit
  ServiceMethod<?> loadServiceMethod(Method method) {
    //缓存中存在取缓存
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        //不存在,解析这个方法的所有注解生成一个ServiceMethod对象,并存入serviceMethodCache
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

//ServiceMethod
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 @Nullable T invoke(Object[] args);
}

ServiceMethod.parseAnnotations内部最终调用了RequestFactory.parseAnnotationsHttpServiceMethod.parseAnnotations,我们分别来看下这两个方法实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
  //请求的方法
  private final Method method;
  private final HttpUrl baseUrl;
  final String httpMethod;
  private final @Nullable String relativeUrl;
  private final @Nullable Headers headers;
  private final @Nullable MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;
  final boolean isKotlinSuspendFunction;

...

  static final class Builder {
    final Retrofit retrofit;
    final Method method;
    //方法的注解数组(可能有多个注解)
    final Annotation[] methodAnnotations; 
    //方法参数的注解数组(每个参数都可能有多个注解)
    final Annotation[][] parameterAnnotationsArray;
    //方法参数类型的数组
    final Type[] parameterTypes;
    //方法类型如GET
    @Nullable String httpMethod;
    boolean hasBody;
    boolean isFormEncoded;
    boolean isMultipart;
     //相对地址如/repos/{owner}/{repo}/contributors
    @Nullable String relativeUrl;
    @Nullable Headers headers;
    @Nullable MediaType contentType;
    //方法注解上需要填写的参数的名称
    @Nullable Set<String> relativeUrlParamNames;
    @Nullable ParameterHandler<?>[] parameterHandlers;
    //是否为kotlin的suspend方法 
    boolean isKotlinSuspendFunction; 

    RequestFactory build() {
      //注解解析
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      ...
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      //参数解析
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }
      ...
      return new RequestFactory(this);
    }
  }
}

RequestFactory主要是来解析方法的注解参数等,也是通过建造者模式创建RequestFactory,我们可以看到RequestFactory.parseAnnotations主要做了三件事:

  1. 首先通过parseMethodAnnotation解析注解,获取它的HTTP方法类型,HTTP的Header,HTTP地址相对路径,需要填充的地址绝对值,是否有body等信息。
  2. 通过ParameterHandler的parseParameter来解析参数的注解,这里使用的是Path,2个参数都有注解,则会创建2个ParameterHandler.Path放进parameterHandlers中来记录参数的注解信息
  3. 信息解析完毕返回RequestFactory对象

接着来看HttpServiceMethod.parseAnnotations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//HttpServiceMethod
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    //是否为kotlin的挂起函数
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      //判断接口方法返回的类型是否是Response
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }
      //注意:将方法返回类型伪装成Call类型,并将SkipCallbackExecutor注解添加到annotations中,因为是协程的话不需要创建线程池
      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      //不是kotlin挂起函数则获取方法的返回类型
      adapterType = method.getGenericReturnType();
    }

    //@1.根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器。例如:RxJava2CallAdapter
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    // 得到响应类型
    Type responseType = callAdapter.responseType();

    ...

    //@2.根据网络请求接口方法的返回值和注解类型从Retrofit对象中获取对应的数据转换器,例如:GsonConverter
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    //将我们之前找到的CallAdapter,和Converter作为参数,返回对应HttpServiceMethod的实现
    if (!isKotlinSuspendFunction) {
      // 不是挂起函数的的走这儿
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //接口方法是挂起函数,返回类型是Response类型
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //接口方法是挂起函数,同时返回类型是body,即自定义的model类型
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }

我们来看@1注解createCallAdapter实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  //HttpServiceMethod
  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    try {
      //noinspection unchecked
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { 
      ...
    }
  }

  //Retrofit
  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
      return nextCallAdapter(null, returnType, annotations);
    }

  public CallAdapter<?, ?> nextCallAdapter(
      @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
    Objects.requireNonNull(returnType, "returnType == null");
    Objects.requireNonNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    //从callAdapterFactories列表里找到一个适合处理这个method的CallAdapter
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      //匹配的原则就是这个CallAdapter要能处理这个返回类型
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    ...
  }

找到一个请求适配器CallAdapter,规则是在前面声明的请求适配器中找到一个能够处理这个返回类型的CallAdapter,我们GitHubService中方法申明返回Call,则会使用系统添加的DefaultCallAdapterFactory来处理,如果方法声明用RXJava来处理,则需要添加一个RXJava的适配器CallAdapter

注释@2中的createResponseConverter实现基本上和createCallAdapter一样,这里我们就不在展开了。

接着我们来看loadServiceMethod(method).invoke(args):

上面已经说过loadServiceMethod(method)最终会返回一个ServiceMethodServiceMethod在执行invoke方法时是实际上调用的是HttpServiceMethod.invoke方法:

1
2
3
4
5
6
7
8
//HttpServiceMethod
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);

内部创建了一个OkHttpCall接着调用了adapt方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
final class OkHttpCall<T> implements Call<T> {

...

  //一个返回okhttp3.Call对象
  @GuardedBy("this")
  private okhttp3.Call getRawCall() throws IOException {
    okhttp3.Call call = rawCall;
    if (call != null) return call;
    ...
    try {
      return rawCall = createRawCall();
    } catch (RuntimeException | Error | IOException e) {
      throwIfFatal(e); // Do not assign a fatal error to creationFailure.
      creationFailure = e;
      throw e;
    }
  }

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

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }
    //调用OkHttp的异步方法
    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }

            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }

          @Override
          public void onFailure(okhttp3.Call call, IOException e) {
            callFailure(e);
          }

          private void callFailure(Throwable e) {
            try {
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
  }

  //同步执行
  @Override
  public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = getRawCall();
    }

    if (canceled) {
      call.cancel();
    }
    //调用OkHttp的同步方法
    return parseResponse(call.execute());
  }

  //创建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;
  }

  //响应结果
  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.
    rawResponse =
        rawResponse
            .newBuilder()
            .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
            .build();

    ...
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      // responseConverter 就是默认的转化器,GsonRequestBodyConverter也可以,序列化成对应的格式
      T body = responseConverter.convert(catchingBody);
      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;
    }
  }
}

可以看到Retrofit内部最终还是通过Okhttp取真正执行网络请求的。

接着看adapt(call, args),我们上面看到了adaptHttpServiceMethod中的一个抽象方法,非Kotlin协程的调用实际是调用了CallAdapted.adapt方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;

    CallAdapted(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, ReturnT> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      //这个callAdapter就是我们之前创建CallAdapted对象时传入的
      return callAdapter.adapt(call);
    }
  }

可以看到内部调用了callAdapter.adapt(call)方法,这个callAdapter就是我们之前调用createCallAdapter方法找到的(见HttpServiceMethod.parseAnnotations内部注释)。它的默认实现实际上是在DefaultCallAdapterFactory中:

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

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

    @Nullable
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
            return null;
        } else if (!(returnType instanceof ParameterizedType)) {
            throw new IllegalArgumentException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
        } else {
            final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType)returnType);
            final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : this.callbackExecutor;
            return new CallAdapter<Object, Call<?>>() {
                public Type responseType() {
                    return responseType;
                }

                public Call<Object> adapt(Call<Object> call) {
                    return (Call)(executor == null ? call : new DefaultCallAdapterFactory.ExecutorCallbackCall(executor, call));
                }
            };
        }
    }

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        //这个delegate实际上就是OkHttpCall
        final Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }
        //异步执行
        public void enqueue(final Callback<T> callback) {
            Objects.requireNonNull(callback, "callback == null");
            this.delegate.enqueue(new Callback<T>() {
                public void onResponse(Call<T> call, Response<T> response) {
                  //放回主线程执行
                    ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
                        if (ExecutorCallbackCall.this.delegate.isCanceled()) {
                            callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                            callback.onResponse(ExecutorCallbackCall.this, response);
                        }

                    });
                }

                public void onFailure(Call<T> call, Throwable t) {
                    ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
                        callback.onFailure(ExecutorCallbackCall.this, t);
                    });
                }
            });
        }

        ...
        //同步执行
        public Response<T> execute() throws IOException {
            return this.delegate.execute();
        }
    }
}

可以看到我们之前创建的OkHttpCall经过adapt方法后Call会被包装为ExecutorCallbackCall类型,这儿使用了装饰模式。然后返回此对象。ExecutorCallbackCall的作用在于包装OkHttpCall,把它的返回结果放到主线程执行。

3.3 执行网络请求

1
2
3
4
5
Call<List<Repo>> repos = service.listRepos("octocat");
//同步执行请求
repos.execute()
//异步执行请求
repos.enqueue(Callback responseCallback)

通过前面的分析知道,此时的Call对象实际上是ExecutorCallbackCall,执行请求时内部实际上调用的是OkHttpCall中方法,而之前我们讲OkHttpCall内部实现时讲过,它实际上是通过Okhttp去真正执行网络请求的。

到此Retrofit的正常流程就分析完了,接下来我们看看Retrofit是如何适配kotlin协程的。

3.4 适配kotlin协程

我们把上面分析过的HttpServiceMethod.parseAnnotations拿过来,这次分析协程逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//HttpServiceMethod
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    //是否为kotlin的挂起函数
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      //判断接口方法返回的类型是否是Response
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }
      //注意:将方法返回类型伪装成Call类型,并将SkipCallbackExecutor注解添加到annotations中,因为是协程的话不需要创建线程池
      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      //不是kotlin挂起函数则获取方法的返回类型
      adapterType = method.getGenericReturnType();
    }

    //@1.根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器。例如:RxJava2CallAdapter
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    // 得到响应类型
    Type responseType = callAdapter.responseType();

    ...

    //@2.根据网络请求接口方法的返回值和注解类型从Retrofit对象中获取对应的数据转换器,例如:GsonConverter
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    //将我们之前找到的CallAdapter,和Converter作为参数,返回对应HttpServiceMethod的实现
    if (!isKotlinSuspendFunction) {
      // 不是挂起函数的的走这儿
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //接口方法是挂起函数,返回类型是Response类型
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //接口方法是挂起函数,同时返回类型是body,即自定义的model类型
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }

可以看到如果方法是kotlin的挂起函数,我们会根据不同的返回值类型来创建SuspendForResponse或者SuspendForBody。只不过SuspendForResponse获取的返回值是responseSuspendForBody获取的是response.body(),我们直接来看SuspendForBody内部实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
    private final boolean isNullable;

    SuspendForBody(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, Call<ResponseT>> callAdapter,
        boolean isNullable) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
      this.isNullable = isNullable;
    }

    @Override
    protected Object adapt(Call<ResponseT> call, Object[] args) {
      // 获取适配的Call
      call = callAdapter.adapt(call);
      //获取Continuation
      //noinspection unchecked Checked by reflection inside RequestFactory.
      Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];

      try {
        return isNullable
            ? KotlinExtensions.awaitNullable(call, continuation)
            : KotlinExtensions.await(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }

首先第一步,适配Call,如果是RxJava,这里的callAdapter就是RxJava2CallAdapter,同时返回的就是Observable,而协程的callAdapter跟我们之前正常流程一样,是Retrofit默认的DefaultCallAdapterFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//DefaultCallAdapterFactory
    @Nullable
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
            return null;
        } else if (!(returnType instanceof ParameterizedType)) {
            throw new IllegalArgumentException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
        } else {
            final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType)returnType);
            //由于之前已经将SkipCallbackExecutor注解添加到annotations中,所以Executor直接为null
            final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : this.callbackExecutor;
            return new CallAdapter<Object, Call<?>>() {
                public Type responseType() {
                    return responseType;
                }

                public Call<Object> adapt(Call<Object> call) {
                  //// 最终调用adapt时候返回的就是它本身的Call,即不需要进行适配。
                    return (Call)(executor == null ? call : new DefaultCallAdapterFactory.ExecutorCallbackCall(executor, call));
                }
            };
        }
    }

接着我们看下面的返回:

1
2
3
 return isNullable
            ? KotlinExtensions.awaitNullable(call, continuation)
            : KotlinExtensions.await(call, continuation);

这里的isNullable目前Retrofit的版本都是false,可能后续会支持空类型。但现在肯定是不支持的,所以直接进入KotlinExtensions.await()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
suspend fun <T : Any> Call<T>.await(): T {
  return suspendCancellableCoroutine { continuation ->
    continuation.invokeOnCancellation {
      cancel()
    }
    //之前讲过这儿实际上执行的时OkHttpCall的enqueue方法
    enqueue(object : Callback<T> {
      override fun onResponse(call: Call<T>, response: Response<T>) {
        if (response.isSuccessful) {
          // 1. 拿到body
          val body = response.body()
          if (body == null) {
            val invocation = call.request().tag(Invocation::class.java)!!
            val method = invocation.method()
            val e = KotlinNullPointerException("Response from " +
                method.declaringClass.name +
                '.' +
                method.name +
                " was null but response body type was declared as non-null")
            // 2. body为空,唤起协程,抛出异常
            continuation.resumeWithException(e)
          } else {
            // 3. 唤起协程,返回body
            continuation.resume(body)
          }
        } else {
          // 4. 唤起协程,抛出异常
          continuation.resumeWithException(HttpException(response))
        }
      }

      override fun onFailure(call: Call<T>, t: Throwable) {
         // 5. 唤起协程,抛出异常
        continuation.resumeWithException(t)
      }
    })
  }
}

可以看到上面的扩展函数通过suspendCancellableCoroutine来创建一个协程,这个协程被取消时会回调invokeOnCancellation 方法,我们可以在这儿做一些释放资源的操作。主要是onResponse回调,协程通过挂起来执行耗时任务,而成功与失败会分别通过resume()resumeWithExecption()来唤起挂起的协程,让它返回之前的挂起点,进行执行。而resumeWithExecption()内部也是调用了resume(),所以协程的唤起都是通过resume()来操作的。调用resume()之后,我们可以在调用协程的地方返回请求的结果。

4. 总结

下面我们用一张图来总结一下Retrofit的核心流程:

Retrofit流程图