Retrofit 是 square 推出用来请求 RESTful 风格 API 的网络库,可以让开发人员快速开发 RESTful 风格的应用。

本文基于 retrofit2.5.0 进行分析。

简单使用

我们先从官方的例子中了解一下怎么使用,相信对于 Android 开发者来说,使用已经非常熟练了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
repos.execute();

例子中先创建了 API 接口,然后创建了 Retrofit 实例,接着调用 retrofit.create 创建了接口实现类,最后就是我们调用网络请求获取数据了。 retrofit 基本的用法就是这样。

下面我们就来一步一步分析

Retrofit.build

Retrofit 使用建造者模式创建 API,我们从 Retrofit.build 开始分析

 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
public Retrofit build() {
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }

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

  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    // 设置回调
    callbackExecutor = platform.defaultCallbackExecutor();
  }

  List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  // 添加适配器
  callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

  // 添加数据转换器
  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 时,先设置了 callFactory ,如果没有手动设置,那么 Retrofit 默认会帮你设置为 OkHttpClient

接下来设置 callbackExecutor ,如果没有设置则会调用 platformdefaultCallbackExecutorplatform 会根据不同的平台返回不同的 Executor , Android 中返回的是 MainThreadExecutor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
static class Android extends Platform {
  @Override public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
  }

  @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    if (callbackExecutor == null) throw new AssertionError();
    return new ExecutorCallAdapterFactory(callbackExecutor);
  }

  static class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override public void execute(Runnable r) {
      handler.post(r);
    }
  }
}

MainThreadExecutor 中看到 Callback 默认是在主线程的。顺便提一下 platform 是在 Builder 的构造方法中设置的,属于太细节,这里就不去分析了。

可以看到接下来设置的 defaultCallAdapterFactory 返回的是 ExecutorCallAdapterFactory

最后设置 converterFactories ,这是用来把服务器结果转换成我们期望的格式,通常我们会转换成 JSONRetrofit 也内置了 BuiltInConverters ,它只能转换 VoidBufferStream 类型。

总结一下 Retrofit#build 干了什么

  1. callFactory 没有设置默认为 OkHttpClient
  2. callbackExecutor Android 平台默认是 MainThreadExecutor ,用来回调请求结果的。
  3. callAdapterFactories Android 平台默认添加 ExecutorCallAdapterFactory ,用来把 Retrofit.Call 转换成其他的 Call 这里其实是 OkHttpCall 。这样 Retrofit.Call 就和别的 Call 高度解耦了。
  4. converterFactories 默认添加 BuiltInConverters ,用来把请求结果转换成对应的 JavaBean

Retrofit.create

Retrofit 的实例创建好了,需要调用 create 来创建接口的实现类。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public <T> T create(final Class<T> 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 Object invoke(Object proxy, Method method, @Nullable Object[] args)
           throws Throwable {
         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);
       }
     });
}

create 方法中使用了动态代理创建接口的实现类,当我们调用接口中的方法会执行 invoke ,第一参数就是调用的对象,第二个参数就是调用对象的某个方法,第三个参数就是方法需要的参数。如果调用的类是 ObjectJava8 的方法,则直接调用。最后返回 loadServiceMethod(method).invoke(args != null ? args : emptyArgs)

loadServiceMethod

接下来我们来看最有料的 loadServiceMethod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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;
}

loadServiceMethod 为了提高性能做了缓存,不然每次都要查找多费时间。最后调用 ServiceMethod.parseAnnotations 生成 ServiceMethod 并返回了。这样看来重点在 parseAnnotations 中,跟进去看看。

parseAnnotations

1
2
3
4
5
6
7
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
  RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

  // 省略一些检查判断...

  return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

首先调用了 RequestFactory.parseAnnotations 生成 RequestFactory ,在 RequestFactory.parseAnnotations 中会根据注解解析出请求方法,请求 URL ,请求头,请求体,表单等信息,代码如下。

 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
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
  return new Builder(retrofit, method).build();
}

Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  // 获取方法上的注解
  this.methodAnnotations = method.getAnnotations();
  // 获取参数类型
  this.parameterTypes = method.getGenericParameterTypes();
  // 获取参数上的注解,一个参数可能有多个注解,所以是个二维数组
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}

RequestFactory(Builder builder) {
  method = builder.method;
  baseUrl = builder.retrofit.baseUrl;
  httpMethod = builder.httpMethod;
  relativeUrl = builder.relativeUrl;
  headers = builder.headers;
  contentType = builder.contentType;
  hasBody = builder.hasBody;
  isFormEncoded = builder.isFormEncoded;
  isMultipart = builder.isMultipart;
  parameterHandlers = builder.parameterHandlers;
}

然后调用了 HttpServiceMethod.parseAnnotations ,生成 ServiceMethod ,接下来看一下 HttpServiceMethod.parseAnnotations 是怎么构建 ServiceMethod 的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {
  CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
  Type responseType = callAdapter.responseType();

  ...

  Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}

HttpServiceMethod.parseAnnotations 先调用了 createCallAdapter 找到对应的 callAdapter 并取出返回值的类型,然后调用 createResponseConverter 把返回值类型传递进去,找到对应的 responseConverter 、最后把它们和 callFactoryrequestFactory 封装成 serviceMethod

接下来看看 CallAdapterresponseConverter 是怎么被创建的

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
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(Retrofit retrofit, Method method) {
  Type returnType = method.getGenericReturnType();
  Annotation[] annotations = method.getAnnotations();
  // 省略部分代码
  return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
}

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

// Retrofit#nextCallAdapter
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
                                         Annotation[] annotations) {
  // 省略部分代码
  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;
    }
  }
}

createCallAdapter 方法调最后调用的是 nextCallAdapter ,它会遍历 callAdapterFactories 根据注解和返回值类型查找合适的 CallAdapter 。在构造 Retrofit 时,我们可以通过 addCallAdapterFactorycallAdapterFactories 添加需要的适配器。

createResponseConverter

 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
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {
  Annotation[] annotations = method.getAnnotations();
  try {
    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);
  }
}


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


// Retrofit#nextResponseBodyConverter
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {

  ...

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

createCallAdapter 一样的套路,遍历 converterFactories 根据注解和返回值类型查找合适的 ConverterloadServiceMethod 做的就是通过返回值和注解生成 CallAdapterResponseConverter ,最后构造 HttpServiceMethod

invoke

loadServiceMethod 最后返回的是 HttpServiceMethod ,所以最后调用的 invoke ,是 HttpServiceMethodinvoke

1
2
3
4
5
// HttpServiceMethod
@Override ReturnT invoke(Object[] args) {
  return callAdapter.adapt(
      new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}

invoke 调用了 callAdapter.adapt ,根据之前的分析知道默认的 callAdapterFactoriesExecutorCallAdapterFactory , 所以这里的 callAdapterExecutorCallAdapterFactory 中返回的匿名的 CallAdapter 。代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@Override public @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  final Type responseType = Utils.getCallResponseType(returnType);
  return new CallAdapter<Object, Call<?>>() {
    @Override public Type responseType() {
      return responseType;
    }

    @Override public Call<Object> adapt(Call<Object> call) {
      return new ExecutorCallbackCall<>(callbackExecutor, call);
    }
  };
}

adapt 方法中返回了 ExecutorCallbackCall 所以调用接口的方法最后返回的是 ExecutorCallbackCall ,也就是我们调用 Retrofit.create 创建的服务,调用其中的方法,最后面其实调用 ExecutorCallbackCall 。 关于 ExecutorCallbackCall 我们后面还会碰到。

小节一下 Retrofit#create 里做了这么几件事

  1. 根据动态代理为每个接口方法创建 ServiceMethod
  2. loadServiceMethod 中根据注解和方法的返回值的类型,生成 requestFactory
  3. HttpServiceMethod.parseAnnotations 中根据注解寻找合适的 CallAdapterResponseConverter 。构建 ServiceMethod(HttpServiceMethod)
  4. HttpServiceMethod#invoke 中调用 callAdapter.adaptRetrofit.Call 适配成 callFactory 能调用的请求,也就是 OkHttpCall

执行请求

 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
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
  this.callbackExecutor = callbackExecutor;
  this.delegate = delegate;
}

@Override public void enqueue(final Callback<T> callback) {
  checkNotNull(callback, "callback == null");

  delegate.enqueue(new Callback<T>() {
      @Override public void onResponse(Call<T> call, final Response<T> response) {
        callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
      }

      @Override public void onFailure(Call<T> call, final Throwable t) {
        callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
      }
    });
}

@Override public Response<T> execute() throws IOException {
  return delegate.execute();
}

在上小节中,调用 invoke 最后得到的是一个 ExecutorCallbackCall ,其中 delegate 是个 OkHttpCall 我们调用 enqueue 其实调用的是 OkHttpCallenqueueexecute 直接调用了 delegate.execute() ,就不说了。

来看 enqueueonResponse 中,最后的的结果会调用 callbackExecutor.execute ,之前我们分析在 Android 中 这个 callbackExecutorMainThreadExecutor ,所以最后的结果是在主线程中被回调的。

OkHttpCall

接下来我们来看看 OkHttpCall 代码如下

 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
@Override public void enqueue(final Callback<T> callback) {
  // ...

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

  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) {
          t.printStackTrace();
        }
      }

      @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) {
          t.printStackTrace();
        }
      }
    });
}

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

enqueue 中先调用了 createRawCall ,而 createRawCall 中调用了 callFactory.newCall ,所以最后是调用了 OkHttpClientnewCall 来创建 OkHttpCall 。 而 requestFactory.create 来创建 okhttpRequest 。这样就把网络请求交给了 OkHttp

解析请求结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {

  // ...
  try {
    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;
  }
}

OkHttpCall 中请求成功后,会调用 parseResponse 来把服务返回的数据转换成对应的 JavaBean 。 而实际进行转换的是 responseBodyConverter.convert

总结

  1. Retrofit 通过动态代理创建 API 的实现类。
  2. 通过 callAdapter 进行请求的转换。把 Retrofit.Call 适配成 OkHttpCall
  3. 通过 responseConverter 进行请求结果的转换。
  4. 具体的网络请求交给 callFactory
  5. 通过 callbackExecutor 把请求的结果往主线程切换。
  6. 通过注解生成 request

总体上讲 Retrofit 实际是对网络框架的一层封装,让其更方便的处理 RESTful 风格的 API。

参考

Retrofit 分析-漂亮的解耦套路

拆轮子系列:拆 Retrofit

Retrofit 源码解析