使⽤示例
以下Retrofit解析版本库均为写作时的最新版本:2.9.0。
先在安卓的构建文件中添加依赖:
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
使用步骤:
- 创建⼀个 interface 作为 Web Service 的请求集合,在⾥⾯⽤注解(Annotation)写⼊需要配置的请求⽅法
public interface GitHubService {
@GET("/notifications")
Call<ResponseBody> getNotici();
@GET("/users/LucasXu01")
Call<ResponseBody> getUser();
}
- 在正式代码⾥⽤ Retrofit 创建出 interface 的实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
- 调⽤创建出的 Service 实例的对应⽅法,创建出相应的可以⽤来发起⽹络请求的Call 对象
Call<ResponseBody> repos = service.getNotici();
Call<ResponseBody> user = service.getUser();
-
使⽤ Call.execute() 或者 Call.enqueue() 来发起请求
repos.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } });
实现原理
Retrofit基于OkHttp进行功能细化以更好使用。
以下是Retrofit的整体实现图,对照着图看接下来的源码解析,会不至于嵌套太深而忘记起点,从而达到整体掌握的全局观视角。总而言之:对照着图,往下看源码解析;看下面的源码解析,多返回来看看图,知道自己走到了哪一步。
通过Retrofit.create(Class)
⽅法创建出 Service interface 的实例,从⽽使得 Service 中配置的⽅法变得可⽤,下面这段create()
代码是 Retrofit 结构的核⼼;
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 {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
create()
代码主要做两件事:验证接口合法性、动态代理接口。
接口的合规验证
验证服务接口validateServiceInterface(service)
:
private void validateServiceInterface(Class<?> service) {
//service必须是接口
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// service不能继承泛型接口
Deque<Class<?>> check = new ArrayDeque<>(1);
check.add(service);
while (!check.isEmpty()) {
Class<?> candidate = check.removeFirst();
if (candidate.getTypeParameters().length != 0) {
StringBuilder message =
new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
if (candidate != service) {
message.append(" which is an interface of ").append(service.getName());
}
throw new IllegalArgumentException(message.toString());
}
Collections.addAll(check, candidate.getInterfaces());
}
// 对每个service方法进行初始化加载试错
if (validateEagerly) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
可以看到,validateServiceInterface(service)
:验证了需要代理的service
必须是接口,且不能继承泛型接口。该方法最后会对每个service方法进行初始化加载试错。
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {}
java接口默认不许有默认实现,但是java8开始可以给接口的一些方法写默认实现了;java接口不允许写静态方法,但java8开始允许接口里写静态方法了。然而Retrofit是不支持的这些的,Retrofit不接纳这两种方式为service接口里的方法。
自定义api的动态代理
有关动态代理的知识可以看这篇文章:Java内功修炼系列:代理模式及动态代理,这里默认读者已有相关知识。
代理:创造一个类并实现了某个接口,这个具体new出来的类就实际上代理这个接口的具体实现,这个类就是代理类。
动态代理:这个代理类在运行时(匿名类都是运行时创建,非编译时)生成。
Retrofit.create() ⽅法内部,使⽤的是Proxy.newProxyInstance() ⽅法来创建 Service 实例。这个⽅法会为参数中的多个 interface (具体到 Retrofifit 来说,是固定传⼊⼀个 interface)创建⼀个对象,这个对象实现了所有 interface 的每个⽅法,并且每个⽅法的实现都是雷同的:调⽤对象实例内部的⼀个 InvocationHandler 成员变量的invoke() ⽅法,并把⾃⼰的⽅法信息传递进去。这样就在实质上实现了代理逻辑:interface 中的⽅法全部由⼀个另外设定的 InvocationHandler 对象来进⾏代理操作。并且,这些⽅法的具体实现是在运⾏时⽣成 interface 实例时才确定的,⽽不是在编译时(虽然在编译时就已经可以通过代码逻辑推断出来)。这就是⽹上所说的「动态代理机制」的具体含义。
Proxy.newProxyInstance()
有三个参数:
1 提供一个类加载器
2 提供代理的接口对象
3 真正代理:实际做操作的对象
由动态代理的知识我们可知,无论哪个service,最终都会调用到invoke方法
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// 如果方法是Object中的方法,不代理,自己用自己的方法。
// 确保代理的方法不是Object中的方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
// 不代理java8的默认方法
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
platform.isDefaultMethod(method) 判断有没有java8的types, 主要是对不同版本的java进行了处理,使得最终都能得到正确结果。
boolean isDefaultMethod(Method method) {
return hasJava8Types && method.isDefault();
}
loadServiceMethod(method).invoke(args);
拆开来看,首先通过loadServiceMethod
获得一个HttpServiceMethod
的实现类,然后调用它的invoke
方法。接下来就看这两个方法。
loadServiceMethod
:一个带缓存的加载,核心: result = ServiceMethod.parseAnnotations(this, method)
;
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;
}
看看result = ServiceMethod.parseAnnotations(this, method)
方法:
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
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);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
点进HttpServiceMethod.parseAnnotations()
中一探究竟:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
...
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
可以看到,一般在java下开发的非协程挂起函数,直接new了一个HttpServiceMethod
的子类CallAdapted
进行返回。
对CallAdapted
的细致分析后面再深入,走到这步回过头去,再看下invoke
方法。
在HttpServiceMethod
中找到了invoke()
方法:
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
可以看到,因为上面返回的是一个HttpServiceMethod
的子类CallAdapted
,所以这里的adapt(call, args)
执行的是类CallAdapted
中的adapt()
方法:
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) {
return callAdapter.adapt(call);
}
}
可以看到adapter的实现就一行return callAdapter.adapt(call)
。这个⽅法会使⽤⼀个 CallAdapter 对象来把 OkHttpCall 对象进⾏转换,⽣成⼀个新的对象,默认情况下,该方法返回的是⼀个 ExecutorCallbackCall
对象 ,它的主要作⽤是把操作切回主线程后再交给 Callback 。
另外,如果有⾃定义的 CallAdapter,这⾥也可以⽣成别的类型的对象,例如RxJava 的 Observable ,来让 Retrofit 可以和 RxJava 结合使⽤。
如何创建的OKHttp
上面说到,在HttpServiceMethod
中的invoke()
方法创建了OkHttpCall
:new OkHttpCall<>(requestFactory, args, callFactory,responseConverter)
OkHttpCall 是 retrofit.Call 的⼦类。这⾏代码负责将ServiceMethod 解读到的信息( RequestFactory 、OkHttpClient 和ResponseConverter )封装进 OkHttpCall ;⽽这个对象可以在需要的时候(例如它的 enqueue() ⽅法被调⽤的时候),利⽤ RequestFactory 和 OkHttpClient 来创建⼀个 okhttp3.Call对象,并调⽤这个 okhttp3.Call 对象来进⾏⽹络请求的发起,然后利⽤ResponseConverter 对结果进⾏预处理之后,交回给 Retrofifit 的Callback 。
如下代码所示,在repos.enqueue(new Callback<ResponseBody>() {}
时,执行的是OkHttpCall
的enqueue
方法:
@Override
public void enqueue(final Callback<T> callback) {
...
okhttp3.Call call;
synchronized (this) {
...
call = rawCall = createRawCall();
}
...
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
// 注释1
response = parseResponse(rawResponse);
callback.onResponse(OkHttpCall.this, response);
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
callback.onFailure(OkHttpCall.this, e);
}
});
}
可以看到,真正执行call.enqueue
的是okhttp3的call
,它在OkHttpCall内部生成,主要通过call = rawCall = createRawCall();
:
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;
}
可以看到OkHttpCall
中通过callFactory
创建,我们知道OkHttp3的的call的创建如下代码所示: client.newCall(request).enqueue(new Callback())
,它需要一个OkHttp3中的Request
对象,它在Retrofit中通过RequestFactory
进行构建,并传给callFactory
创造出OkHttp3的Call
对象。
对照着前文的结构图看,否则容易迷失。callFactory
对象在HttpServiceMethod
中的invoke()
方法中创建OkHttpCall
时被赋值,它的创建在HttpServiceMethod
的parseAnnotations()
方法中:
okhttp3.Call.Factory callFactory = retrofit.callFactory;
可以看到,这个用来创建OkHttp3的Call
的工厂来自于Retrofit,在Retrofit中的构建者模式中可以找到:
public Retrofit build() {
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
..
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
}
真相大白了!原来Retrofit用来创建OkHttp3的Call
的工厂就是OkHttp3的OkHttpClient
:callFactory = new OkHttpClient();
如何解析返回结果
回看前结构图,可以知道请求结果的返回,在前一章节:如何创建的OKHttp 的注释1处:
response = parseResponse(rawResponse);
查看OkHttpCall的parseResponse方法:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
...
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
}
}
可以看到,网络请求的结果最终会被一个返回结果转换器进行转换之后再返回,不难猜测,这个responseConverter
转换器的功能,就是将网络返回的不易看懂的数据转换为我们需要的自定义的Object接收对象,如UserBean、XXListBean等。现在我们已经有了原始的返回对象,接下只需要知道这个responseConverter
对象是什么以及它的convert()
方法即可。
还是在HttpServiceMethod
的invoke()
方法中寻找OkHttpCall
的创建过程,responseConverter
作为构建参数被传递进来。而它又是在HttpServiceMethod
的parseAnnotations()
方法中被create:
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
看createResponseConverter()
方法
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(responseType, annotations)
方法:
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
继续追到Retrofit里的nextResponseBodyConverter(null, type, annotations);
:
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(...) {
...
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;
}
}
...
}
由converterFactories.get(i).responseBodyConverter(type, annotations, this);
可以看到,这个返回结果转换器responseConverter
来自于converterFactories
,在Retrofit中寻找converterFactories
,在Retrofit的建造者Builder的build()
方法中我们找到:
public Retrofit build() {
...
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
...
}
第一行和第三行被add的converter不是我们自定义的,暂不去看,去寻找第二行addAll(this.converterFactories)
中的converterFactories
,看它是哪里被赋值构建的,我们于是又在Retrofit中找到了addConverterFactory()
方法:
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
这个方法是不是很眼熟,回忆一下我们平时是怎么使用Retrofit的:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(gsonConvertFactory)
.build();
这不就是我们在一开始在创建Retrofit时常用的添加Gson转换器的地方嘛!原来这个Gson转化器在Retrofit里是最终被用到OkHttpCall的parseResponse()
中的responseConverter.convert(catchingBody);
啊!原来Retrofit内部的网络结果转换器是这样工作的!
返回的UI线程切换原理
相比OkHttp3,Retrofit在使用时一个很明显的方便之处就是在 Call.execute() 或者 Call.enqueue() 来发起请求后的返回结果事件中,不需要再切换线程,因为此刻,它已经在安卓的UI主线程当中了。
repos.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
在在执行retrofit2.Call
的enqueue()
方法时,我们需要注意,这个Call对象我们刚刚是在HttpServiceMethod
中的invoke()
方法创建的OkHttpCall
:new OkHttpCall<>(requestFactory, args, callFactory,responseConverter)
,但是这个OkHttpCall
会经过adapt转为真正进行请求的另一个类ExecutorCallbackCall
,它里面会持有OkHttpCall
并在执行enqueue
方法时去执行OkHttpCall
的enqueue
方法。
我们其实可以顺着HttpServiceMethod
中的CallAdapted
子类找到callAdapter.adapt(call)
,顺着这个adapt(call)
方法不断溯源,可以找到这个callAdapter
的赋值过程实际上是在Retrofit
中的build函数中,再在Retrofit
中的build()
方法中不断溯源,最终可以找到它在Retrofit
中赋值如下所示:
public CallAdapter<?, ?> nextCallAdapter(...) {
...
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
}
可以看到,callAdapter
最终取自 callAdapterFactories
,它是定义在Retrofit中的callAdapter
的工厂List,具体每一个callAdapter
由这个List中的某一个工厂的get()
方法进行创建。
那么问题来了, callAdapterFactories
这个List中的工厂又在哪里来的呢?再去寻找 callAdapterFactories
,如下所示, callAdapterFactories
中添加的是platform.defaultCallAdapterFactories(callbackExecutor)
对象:
public Retrofit build() {
...
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
//注释2
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
...
}
那么问题来了:
-
platform.defaultCallAdapterFactories()
这个方法干嘛的? -
callbackExecutor
哪里来的,有什么用?
首先看platform.defaultCallAdapterFactories()
方法:
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
该方法主要创建了DefaultCallAdapterFactory
类,这里需要中断注意下,刚刚说了,具体每一个callAdapter
由 callAdapterFactories
这个List中的某一个工厂的get()
方法进行创建的,所以,我们此刻应该去DefaultCallAdapterFactory
类中看看它的get()
方法做了什么:
public @Nullable CallAdapter<?, ?> get(...) {
...
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
来了!get()
方法它创建了一个CallAdapter
进行返回,这不就是在HttpServiceMethod
里invoke()
方法返回的那个adapt()
,我们再看一下:
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
对了!是它了,HttpServiceMethod
的invoke()
方法里执行的adapt()
就是return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
这个了!它把OkHttpCall
传给了ExecutorCallbackCall
,通过前面的分析不难想象,最终的请求ExecutorCallbackCall
还是通过这个OkHttpCall
来进行的,那么,第二个问题还没解决,这个executor
是什么?干嘛用的?
回到callAdapterFactories
添加platform.defaultCallAdapterFactories(callbackExecutor)
对象那里,可以看到注释2:
callbackExecutor = platform.defaultCallbackExecutor();
这个就是哪个executor
!看它的实现:
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
追MainThreadExecutor()
:
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
这不就是在切线程!而且拿的是Looper.getMainLooper()
,难不成这就是Retrofit返回直接在UI主线程的原因嘛?汇过去看这个executor
的使用地方,也就是ExecutorCallbackCall
去执行enqueue()
进行网络请求时的使用情况:
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
public void enqueue(final Callback<T> callback) {
this.delegate.enqueue(new Callback<T>() {
public void onResponse(Call<T> call, Response<T> response) {
ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
...
callback.onResponse(ExecutorCallbackCall.this, response);
});
}
public void onFailure(Call<T> call, Throwable t) {
ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
callback.onFailure(ExecutorCallbackCall.this, t);
});
}
});
}
}
由上面的分析可知,ExecutorCallbackCall
中的delegate
就是 adapt()
传过去的OkHttpCall
,callbackExecutor
就是我们刚刚看到的MainThreadExecutor
,ExecutorCallbackCall
在处理返回结果时,使用的是MainThreadExecutor
,而MainThreadExecutor
又将这个线程切换到了UI主线程中,至此,完成了网络请求过程子线程个UI主线程的切换。
参考
https://square.github.io/retrofit/