Retrofit

官话: A type-safe HTTP client for Android and Java

我的理解: 它提供了一种方便的 HTTP 请求编写方式. 它通过解析接口方法的注解, 构造出对应的 HTTP 请求方法, 并且支持添加自己的 CallAdapter 和 Converter 定制化请求的创建和结果的解析.

定义 HTTP 接口方法

1
2
3
4
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}

创建 Retrofit 实例和请求方法

1
2
3
4
5
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();

GitHubService service = retrofit.create(GitHubService.class);

发出请求并获取结果

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

下图是以 Rxjava2CallAdapter 为 CallAdapter 时, 在 create 之后, 调用方法的大致流程:

Retrofit流程

Retrofit 的构造

  • 在多处使用了建造者模式, 工厂模式
  • 在接口的实现处使用了动态代理

Retrofit.Builder

一些配置参数:

属性 类型 说明
platform Platform 代码运行的平台, Retrofit 提供两个默认的 Andorid 和 Java
callFactory okhttp3.Call.Factory 请求的构造器
baseUrl HttpUrl 所有请求的BaseUrl
converterFactories List<Converter.Factory> 结果的转化器集
callAdapterFactories List<CallAdapter.Factory> 请求的适配器转化集
callbackExecutor Executor Java的Executor,结果回调执行的线程池
validateEagerly boolean 是否提前验证的标志

通过 Builder 构造 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
public Retrofit build() {

// 请求构造器,默认为 OkHttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}

// 回调执行的线程池,默认为平台默认的,在 Android 上为 MainExecutor
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}

// 添加默认的 callAdapterFactor
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());

// 添加自带的转换器,确保能转化所有类型
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);

// 构造 Retrofit 实例
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

创建 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
public <T> T create(final Class<T> service) {
// 验证传入的参数是否是一个没有继承其他接口的接口
Utils.validateServiceInterface(service);
// 如果设置了提前验证,会在 create 时就构造 serviceMethod,加入缓存.,
if (validateEagerly) {
eagerlyValidateMethods(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 the method is a method from Object then defer to normal invocation.
// 比如 toString, hashCode, equal 等方法会直接反射调用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 如果是平台自有的方法,则通过平台调用
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 构造一个 serviceMethod 来执行真正的操作
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
}
);
}

可以看出创建过程就是为我们定义的接口创建代理对象,当调用方法时通过代理对象去执行真正的操作.

ServiceMethod

在调用 Retrofit 的 create 最后,会调用 loadServiceMethod 返回 ServiceMethod 实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;

synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 通过 parseAnnotations 静态方法获得实例
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}

parseAnnotations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// RequestFactory 里储存了请求相关的参数, HTTP Method, headers, contentType 等
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

Type returnType = method.getGenericReturnType();
// 检查返回值类型
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
// 返回值不能是 void,如需要可以使用 void 的包装类 Void
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
// 返回 HtppServiceMethod
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

HttpServiceMethod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// 创建 CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
// HEAD 请求的返回值必须是 Void 类型
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
// 创建 ResponseConverter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);

okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}

最终执行请求时,会走到 serviceMethod 的 invoke 处:

1
2
3
4
5
6
@Override ReturnT invoke(Object[] args) {
// 这里的 callAdapter 是从 Retrofit 的 callAdapterFactories 中找到匹配请求方法返回值的 callAdapter
// 不单独 addCallAdapterFactory 话,默认就是 platform 提供的
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}

至此, Retrofit 就将 interface 定义的接口方法通过动态代理,转换成了匹配 interface 方法返回值的 CallAdapter.

RxJava2CallAdapterFactory

常用的 RxJava2CallAdapterFactory, 会匹配返回值是 Observable, Single, Flowable Maybe.

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
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false, false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
...
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
...
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
...
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);
}

接口的 Proxy invoke 时会调到 adapt 方法,返回声明的返回值. RxJava2Adapter 这里可以返回几种 Observeable. 当对这些 Observable 进行 subscribe时, 会走到 CallExecuteObservableCallEnqueueObservableonSubscribeActual 方法.

  • CallEnqueueObservable 里会调用 OkHttpCall 的 enqueue 异步发起请求
  • CallExecuteObservable 里会调用 OkHttpCall 的 execute 同步发起请求
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
@Override public Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);

Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}

if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}

if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}