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.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
时, 会走到 CallExecuteObservable
或 CallEnqueueObservable
的 onSubscribeActual
方法.
- 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;
}
|