一. 前言
- Retrofit: A type-safe HTTP client for Android and Java.
二. Demo
Demo
引入 Retrofit
1
2
3dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
}发起一个网络请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24interface ApiService {
fun getUserData(): Call<ResponseBody>
}
fun main() {
val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.build()
val service = retrofit.create(ApiService::class.java)
val call: Call<ResponseBody> = service.getUserData()
call.enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
val userBean = response.body()?.string()
println("userBean: $userBean")
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
println("onFailure: $t")
}
})
}输出结果
1
userBean: {"userName":"JBl","userAge":7816977017260632}
Retrofit 是建立在 OkHttp 之上的一个网络请求封装库,内部依靠 OkHttp 来完成实际的网络请求。Retrofit 在使用上很简洁,API 是通过 interface 来声明的,只需要通过 interface 来声明API 路径、请求方式、请求参数、返回值类型等各个配置项,然后调用方法就可以发起网络请求
从上述例子可以看到,
getUserData()
方法所代表的 API 的请求结果是一个 Json 格式的字符串,其返回值类型被定义为Call<ResponseBody>
,此处的ResponseBody
即okhttp3.ResponseBody
,是 OkHttp 提供的对网络请求结果的包装类,Call 即retrofit2.Call
,是 Retrofit 对okhttp3.Call
做的一层包装,OkHttp 在实际发起请求的时候使用的回调是okhttp3.Call
,回调内部就会来中转调用retrofit2.Call
,以便将请求结果转交给外部
converter-gson
上述例子虽然简单,但还不够方便,因为既然 API 的返回值我们已知就是 Json 格式的了,那么我们自然就希望
getUserData()
方法的返回值直接就是一个 Bean 对象,而不是拿到一个 String 对象后还需要自己再去进行反序列化,这可以通过 converter-gson 这个库来达到这个效果1
2
3
4dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
}修改代码,然后就可以直接在 Callback 中拿到 UserBean 对象了
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
27interface ApiService {
fun getUserData(): Call<UserBean>
}
data class UserBean(val userName: String, val userAge: Long)
fun main() {
val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(ApiService::class.java)
val call: Call<UserBean> = service.getUserData()
call.enqueue(object : Callback<UserBean> {
override fun onResponse(call: Call<UserBean>, response: Response<UserBean>) {
val userBean = response.body()
println("userBean: $userBean")
}
override fun onFailure(call: Call<UserBean>, t: Throwable) {
println("onFailure: $t")
}
})
}
adapter-rxjava2
再然后,如果我们也看
Call<UserBean>
不爽,想要通过 RxJava 的方式来进行网络请求也是可以的,此时就需要再使用到 adapter-rxjava2 这个库了1
2
3
4
5dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
}修改代码,此时就完全不用使用到
Call.enqueue()
来显式发起网络请求了,当进行subscribe()
的时候就会触发网络请求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
28interface ApiService {
fun getUserData(): Observable<UserBean>
}
data class UserBean(val userName: String, val userAge: Long)
fun main() {
val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
val service = retrofit.create(ApiService::class.java)
val call: Observable<UserBean> = service.getUserData()
call.subscribe(object : Consumer<UserBean> {
override fun accept(userBean: UserBean?) {
println("userBean: $userBean")
}
}, object : Consumer<Throwable> {
override fun accept(t: Throwable?) {
println("onFailure: $t")
}
})
}
三个问题
- 优点:Retrofit 在抽象程度上是很高的。不管是需要 Call 类还是 Observable 类型的包装类,只需要添加不同的 CallAdapterFactory 即可,就算想返回 LiveData 类型都是可以实现的。也不管是需要 ResponseBody 类型还是具体的 Bean 对象类型,也只需要添加不同的 ConverterFactory 即可,就算 API 的返回值是 XML 格式也可以进行映射解析
- 问题
- 问题一:Retrofit 是如何将 interface 内部的方法转化为一个个实际的 GET、POST、DELETE 等各式各样的网络请求?例如,Retrofit 是如何将
getUserData()
转换为一个 OkHttp 的 GET 请求? - 问题二: Retrofit 是如何将 API 的返回值映射为具体的 Bean 对象?例如,ResponseBody 是如何映射为 UserBean?
- 问题三:Retrofit 是如何抽象不同的 API 返回值包装类?例如,Call 是如何替换为 Observable ?
- 问题一:Retrofit 是如何将 interface 内部的方法转化为一个个实际的 GET、POST、DELETE 等各式各样的网络请求?例如,Retrofit 是如何将
三. 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
22
23
24
25
26
27public <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 the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
//如果外部调用的是 Object 中声明的方法的话则直接调用
//例如 toString()、hashCode() 等方法
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
//根据 method 是否默认方法来决定如何调用
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}- 这里的重点就是 Proxy.newProxyInstance 所实现的动态代理模式了。通过动态代理,Retrofit 会将我们对 ApiService 的调用操作转发给 InvocationHandler 来完成
- Retrofit 在后续会通过反射拿到我们在声明
getUserData()
时标注的各个配置项,例如API 路径、请求方式、请求参数、返回值类型等各个信息,然后将这些配置项拼接为 OkHttp 的一个原始网络请求。当我们调用了call.enqueue()
方法时,这个操作就会触发 InvocationHandler 去发起 OkHttp 网络请求了
Retrofit 会根据 method 是否是默认方法来决定如何调用,这里主要看
loadServiceMethod(method)
方法,该方法的主要逻辑是将每个代表接口方法的 method 对象转换为 ServiceMethod 对象,该对象中就包含了 API 的具体信息
因为 API 可能先后会被调用多次,所以将构造出来的 ServiceMethod 对象缓存到 serviceMethodCache 中以实现复用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
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;
}
四. ServiceMethod
从上面可知,
loadServiceMethod(method)
方法返回的是一个 ServiceMethod 对象,从名字上来看也可以猜出,每个 ServiceMethod 对象就对应一个 API 接口方法,其内部就包含了对 API 的解析结果。loadServiceMethod(method).invoke(args)
这个操作就对应调用 API 方法并传递参数这个过程,即对应val call: Call<ResponseBody> = service.getUserData()
这个过程ServiceMethod 是一个抽象类,仅包含一个抽象的
invoke(Object[] args)
方法。ServiceMethod 使用到了工厂模式,由于 API 的最终请求方式可能是多样化的,既可能是通过线程池来执行,也可能是通过 Kotlin 协程来执行,使用工厂模式的意义就在于可以将这种差异都隐藏在不同的 ServiceMethod 实现类中,而外部统一都是通过parseAnnotations()
方法来获取 ServiceMethod 的实现类parseAnnotations()
方法返回的 ServiceMethod 实际上是 HttpServiceMethod,所以重点就要来看HttpServiceMethod.parseAnnotations()
方法返回的 HttpServiceMethod 具体是如何实现的,并是如何拼接出一个完整的 OkHttp 请求调用链1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//requestFactory 包含了对 API 的注解信息进行解析后的结果
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
//如果返回值包含未确定的泛型类型或者是包含通配符的话,那么就抛出异常
//因为 Retrofit 无法构造出一个不具有确定类型的对象作为返回值
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
//返回值类型不能是 void
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
//重点
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
五. HttpServiceMethod
通过查找引用,可以知道 ServiceMethod 这个抽象类的直接子类只有一个,即 HttpServiceMethod。HttpServiceMethod 也是一个抽象类,其包含两个泛型声明:ResponseT 表示的是 API 方法返回值的外层包装类型,ReturnT 表示的是我们实际需要的数据类型。例如,对于
fun getUserData(): Call<UserBean>
方法,ResponseT 对应的是 Call,ReturnT 对应的是 UserBean此外,HttpServiceMethod 也实现了父类的
invoke()
方法,并将操作转交给了另一个抽象方法adapt()
来完成,所以说,API 方法对应的网络请求具体的发起操作主要看adapt()
方法即可1
2
3
4
5
6
7
8
9
10
11
12
13abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
final ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract ReturnT adapt(Call<ResponseT> call, Object[] args);
···
}再来看
HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)
方法是如何构建出一个 HttpServiceMethod 对象的,并且该对象的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
61abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
/**
* Inspects the annotations on an interface method to construct a reusable service method that
* speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
* method only once and reuse it.
*/
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
//是否是 Suspend 函数,即是否以 Kotlin 协程的方式来进行请求
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
//省略 Kotlin 协程的一些处理逻辑
} else {
adapterType = method.getGenericReturnType();
}
//重点1
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
//拿到包装类内部的具体类型,例如,Observable<UserBean> 内部的 UserBean
//responseType 不能是 okhttp3.Response 或者是不包含具体泛型类型的 Response
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(
method,
"'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
//重点2
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
//重点3
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
//省略 Kotlin 协程的一些处理逻辑
···
}
···
}Retrofit 目前已经支持以 Kotlin 协程的方式来进行调用了,但本例子和协程无关,所以此处先忽略协程相关的处理逻辑,后面会再讲解,
parseAnnotations()
方法的主要逻辑是:- 先通过
createCallAdapter(retrofit, method, adapterType, annotations)
方法拿到 CallAdapter 对象,CallAdapter 就用于实现 API 方法的不同返回值包装类处理逻辑。例如,getUserData()
方法的返回值包装类类型如果是 Call ,那么返回的 CallAdapter 对象就对应 DefaultCallAdapterFactory 包含的 Adapter;如果是 Observable,那么返回的就是 RxJava2CallAdapterFactory 包含的 Adapter - 再通过
createResponseConverter(retrofit, method, responseType)
方法拿到 Converter 对象,Converter 就用于实现 API 方法的不同返回值处理逻辑。例如,getUserData()
方法的目标返回值类型如果是 ResponseBody ,那么 Converter 对象就对应 BuiltInConverters;如果是 UserBean,那么就对应 GsonConverterFactory - 根据前两个步骤拿到的值,构造出一个 CallAdapted 对象并返回
- 先通过
CallAdapted 正是 HttpServiceMethod 的子类,在 InvocationHandler 中通过
loadServiceMethod(method).invoke(args)
发起的调用链,会先创建出一个 OkHttpCall 对象,并最后调用到callAdapter.adapt(call)
方法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
28abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
final ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
}
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;
}
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
六. OkHttpCall
OkHttpCall 是实际发起 OkHttp 请求的地方。当我们调用
fun getUserData(): Call<ResponseBody>
方法时,返回的 Call 对象实际上是 OkHttpCall 类型,而当我们调用call.enqueue(Callback)
方法时,enqueue()
方法中会发起一个 OkHttp 请求,传入的 Callback 对象就会由okhttp3.Callback
本身收到回调时再进行中转调用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
58final class OkHttpCall<T> implements Call<T> {
private final RequestFactory requestFactory;
private final Object[] args;
private final okhttp3.Call.Factory callFactory;
private final Converter<ResponseBody, T> responseConverter;
private volatile boolean canceled;
"this") (
private okhttp3.Call rawCall;
"this") // Either a RuntimeException, non-fatal Error, or IOException. (
private Throwable creationFailure;
"this") (
private boolean executed;
public void enqueue(final Callback<T> callback) {
···
okhttp3.Call call;
···
call.enqueue( new okhttp3.Callback() {
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
}
}
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
}
}
});
}
}
七. 总结
1 | interface ApiService { |
首先,我们通过
retrofit.create(ApiService::class.java)
得到一个 ApiService 的动态实现类,这是通过 Java 原生提供的Proxy.newProxyInstance 代表的动态代理功能来实现的。在拿到 ApiService 的实现类后,我们就可以直接调用 ApiService 中声明的所有方法了当我们调用了
service.getUserData()
方法时,Retrofit 会将每一个 API 方法都抽象封装为一个 ServiceMethod 对象并缓存起来,我们的操作会转交给 ServiceMethod 来完成,由 ServiceMethod 来负责返回我们的目标类型,对应的是ServiceMethod.invoke(Object[] args)
方法,args 代表的是我们调用 API 方法时需要传递的参数,对应本例子就是一个空数组1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//requestFactory 包含了对 API 的注解信息进行解析后的结果
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
//如果返回值包含未确定的泛型类型或者是包含通配符的话,那么就抛出异常
//因为 Retrofit 无法构造出一个不具有确定类型的对象作为返回值
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
//返回值类型不能是 void
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
//重点
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}实际上,ServiceMethod 只具有一个唯一的直接子类,即 HttpServiceMethod,而 HttpServiceMethod 会在
invoke()
方法中构建出一个 OkHttpCall 对象,然后调用其抽象方法adapt()
此外,对于不同的请求方式,
ServiceMethod.parseAnnotations()
方法最终会返回不同的 HttpServiceMethod 子类。对应本例子,最终返回的会是 CallAdapted 对象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
32abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
final ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract ReturnT adapt(Call<ResponseT> call, Object[] args);
···
}
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;
}
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}所以,当我们调用
val call: Call<ResponseBody> = service.getUserData()
时,返回的Call<ResponseBody>
实际上是OkHttpCall<ResponseBody>
当我们调用
call.enqueue()
方法时,OkHttpCall 的enqueue()
方法内部就会发起一个 OkHttp 请求,并为这个请求设置一个回调对象okhttp3.Callback
,然后在这个回调中再来回调我们传递进去的retrofit2.Callback
。这样,外部也就可以收到网络请求成功或者失败的事件回调了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
43final class OkHttpCall<T> implements Call<T> {
@Override
public void enqueue(final Callback<T> callback) {
···
okhttp3.Call call;
···
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
}
}
});
}
}
八. API 方法是如何解析的
问题一:Retrofit 是如何将 interface 内部的方法转化为一个个实际的 GET、POST、DELETE 等各式各样的网络请求的?例如,Retrofit 是如何将 getUserData() 转换为一个 OkHttp 的 GET 请求的?
这个过程在 ServiceMethod 的
parseAnnotations()
方法中就已经完成的了,对应的是RequestFactory.parseAnnotations(retrofit, method)
方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21abstract class ServiceMethod<T> {
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);
}
abstract @Nullable T invoke(Object[] args);
}前文说了,Retrofit 是建立在 OkHttp 之上的一个网络请求封装库,内部依靠 OkHttp 来完成实际的网络请求。而 OkHttp 的一般请求方式如下所示
1
2
3
4
5
6
7
8
9
10
11OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}OkHttp 需要构建一个 Request 对象来配置请求方式和请求参数,并以此来发起网络请求。所以,Retrofit 也需要一个构建 Request 对象的过程,这个过程就隐藏在 RequestFactory 中
RequestFactory 采用了 Builder 模式,这里无需过多理会其构建过程,我们只要知道 RequestFactory 中包含了对 API 方法的各项解析结果即可。其
create(Object[] args)
方法就会根据各项解析结果,最终返回一个okhttp3.Request
对象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
56final 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;
okhttp3.Request create(Object[] args) throws IOException {
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args.length;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException(
"Argument count ("
+ argumentCount
+ ") doesn't match expected count ("
+ handlers.length
+ ")");
}
RequestBuilder requestBuilder =
new RequestBuilder(
httpMethod,
baseUrl,
relativeUrl,
headers,
contentType,
hasBody,
isFormEncoded,
isMultipart);
if (isKotlinSuspendFunction) {
// The Continuation is the last parameter and the handlers array contains null at that index.
argumentCount--;
}
List<Object> argumentList = new ArrayList<>(argumentCount);
for (int p = 0; p < argumentCount; p++) {
argumentList.add(args[p]);
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
}
}OkHttpCall 是实际上发起网络请求的地方,所以最终 RequestFactory 的
create()
方法会由 OkHttpCall 的createRawCall()
方法来调用1
2
3
4
5
6
7
8
9
10
11final class OkHttpCall<T> implements Call<T> {
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;
}
}
九. ResponseBody 是如何映射为 UserBean 的
问题二:Retrofit 是如何将 API 的返回值映射为具体的 Bean 对象的?例如,ResponseBody 是如何映射为 UserBean 的?
OkHttp 默认的接口返回值对象就是 ResponseBody,所以在使用 Retrofit 时如果不引入 converter-gson,我们只能将接口请求结果都定义为 ResponseBody,而不能是具体的 Bean 对象,因为 Retrofit 无法自动地完成 ResponseBody 到 UserBean 之间的转换操作,需要我们将这种转换规则告知 Retrofit
1
2
3
4
5
6
7
8
9interface ApiService {
fun getUserData1(): Call<ResponseBody>
fun getUserData2(): Call<UserBean>
}这种转换规则被 Retrofit 定义为 Converter 接口,对应它的
responseBodyConverter()
方法1
2
3
4
5
6
7
8
9
10
11
12
13
14public interface Converter<F, T> {
T convert(F value) throws IOException;
abstract class Factory {
//将 ResponseBody 转换为目标类型 type
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
}
}为了能直接获取到 UserBean 对象,我们需要在构建 Retrofit 对象的时候添加 GsonConverterFactory
1
2
3
4val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.addConverterFactory(GsonConverterFactory.create())
.build()GsonConverterFactory 会根据目标类型 type,通过 Gson 来进行反序列化出 UserBean 对象
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
36public final class GsonConverterFactory extends Converter.Factory {
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
···
}
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
T convert(ResponseBody value) throws IOException { public
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}问题又来了,Retrofit 是如何知道什么类型才可以交由 GsonConverterFactory 来进行处理的?至少 ResponseBody 就不应该交由 GsonConverterFactory 来处理,Retrofit 如何进行选择?
首先,当我们在构建 Retrofit 对象时传入了 GsonConverterFactory,最终 Retrofit 会对所有 Converter.Factory 进行排序,
converterFactories()
中 BuiltInConverters 会被默认排在第一位,BuiltInConverters 是 Retrofit 自带的对 ResponseBody 进行默认解析的 Converter.Factory 实现类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public final class Retrofit {
public static final class Builder {
public Retrofit build() {
···
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
}
}而 BuiltInConverters 的
responseBodyConverter()
方法在目标类型并非 ResponseBody、Void、Unit 等三种类型的情况下会返回 null1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25final class BuiltInConverters extends Converter.Factory {
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
if (checkForKotlinUnit) {
try {
if (type == Unit.class) {
return UnitResponseBodyConverter.INSTANCE;
}
} catch (NoClassDefFoundError ignored) {
checkForKotlinUnit = false;
}
}
return null;
}
}而 Retrofit 类的
nextResponseBodyConverter()
方法就是为每一个 API 方法选择 Converter 进行返回值数据类型转换的方法。该方法会先遍历到 BuiltInConverters,发现其返回了 null,就会最终选择到 GsonResponseBodyConverter,从而完成数据解析。如果最终没有找到一个合适的处理器的话,就会抛出IllegalArgumentException
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
Objects.requireNonNull(type, "type == null");
Objects.requireNonNull(annotations, "annotations == null");
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;
}
}
···
throw new IllegalArgumentException(builder.toString());
}
十. Call 是如何替换为 Observable 的
问题三:Retrofit 是如何抽象不同的 API 返回值包装类的?例如,Call 是如何替换为 Observable 的?
Retrofit 在默认情况下也只支持将
retrofit2.Call
作为 API 接口的返回数据类型包装类,为了支持返回 Observable 类型,我们需要在构建 Retrofit 的时候添加 RxJava2CallAdapterFactory1
2
3
4
5val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()Retrofit 将
retrofit2.Call
转换为 Observable 的这种规则抽象为了 CallAdapter 接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public interface CallAdapter<R, T> {
//返回具体的内部类型,即 UserBean
Type responseType();
//用于将 Call 转换为 Observable
T adapt(Call<R> call);
abstract class Factory {
//用于提供将 Call<UserBean> 转换为 Observable<UserBean> 的 CallAdapter 对象
//此处的 returnType 即 Observable<UserBean>
//如果此 CallAdapter 无法完成这种数据类型的转换,那么就返回 null
public abstract CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit);
}
}对于 RxJava2CallAdapterFactory 的
get()
方法而言,如果返回值类型并非 Completable、Flowable、Single、Maybe 等类型的话就会返回 null,否则就返回 RxJava2CallAdapter 对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
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;
}
// ...
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);
}
}对于本例子而言,最终 RxJava2CallAdapter 又会返回 CallExecuteObservable,CallExecuteObservable 又会在外部进行
subscribe()
的时候调用call.execute()
方法来发起网络请求,所以在上面的例子中我们并不需要显式地发起网络请求,而是在进行subscribe(
) 的时候就自动触发请求了,Observer 只需要等待网络请求结果自动回调出来即可1
2
3
4
5
6
7
8
9
10
11
12
13
14
15final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
public Type responseType() {
return responseType;
}
public Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable =
isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call);
// ...
return RxJavaPlugins.onAssembly(observable);
}
}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
46final class CallExecuteObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallExecuteObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override
protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallDisposable disposable = new CallDisposable(call);
observer.onSubscribe(disposable);
if (disposable.isDisposed()) {
return;
}
boolean terminated = false;
try {
//发起网络请求
Response<T> response = call.execute();
if (!disposable.isDisposed()) {
//将请求结果传给外部
observer.onNext(response);
}
if (!disposable.isDisposed()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposable.isDisposed()) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
// ...
}问题又来了,Retrofit 是如何知道什么类型才可以交由 RxJava2CallAdapterFactory 来进行处理的?
首先,当我们在构建 Retrofit 对象时传入了 RxJava2CallAdapterFactory,最终 Retrofit 会按照添加顺序对所有 CallAdapter.Factory 进行保存,且默认会在队尾添加一个 DefaultCallAdapterFactory,用于对包装类型为
retrofit2.Call
的情况进行解析而 Retrofit 类的
nextCallAdapter()
方法就是为每一个 API 方法选择 CallAdapter 进行返回值数据类型转换的方法。该方法会先遍历到 RxJava2CallAdapter ,发现其返回了非 null 值,之后就交由其进行处理1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public CallAdapter<?, ?> nextCallAdapter(
Type returnType, Annotation[] annotations) { CallAdapter.Factory skipPast,
Objects.requireNonNull(returnType, "returnType == null");
Objects.requireNonNull(annotations, "annotations == null");
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;
}
}
// ...
throw new IllegalArgumentException(builder.toString());
}
十一. 数据转换流程总结
在默认情况下,我们从回调 Callback 中取到的最原始的返回值类型是 Response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24interface ApiService {
fun getUserData(): Call<ResponseBody>
}
fun main() {
val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.build()
val service = retrofit.create(ApiService::class.java)
val call: Call<ResponseBody> = service.getUserData()
call.enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
val userBean = response.body()?.string()
println("userBean: $userBean")
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
println("onFailure: $t")
}
})
}而在引入了 converter-gson 和 adapter-rxjava2 之后,我们可以直接拿到目标类型 UserBean
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
28data class UserBean(val userName: String, val userAge: Long)
interface ApiService {
fun getUserData(): Observable<UserBean>
}
fun main() {
val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync())
.build()
val service = retrofit.create(ApiService::class.java)
val call: Observable<UserBean> = service.getUserData()
call.subscribe(object : Consumer<UserBean> {
override fun accept(userBean: UserBean?) {
println("userBean: $userBean")
}
}, object : Consumer<Throwable> {
override fun accept(t: Throwable?) {
println("onFailure: $t")
}
})
}Retrofit 要达到这种转换效果,就要先后进行两个步骤:
- 将 ResponseBody转换为 UserBean,从而可以得到 API 返回值
Response<UserBean>
- 将 Call 转换为 Observable,Observable 直接从
Response<UserBean>
中把 UserBean 取出来作为返回值来返回,从而直接得到目标类型 UserBean
- 将 ResponseBody转换为 UserBean,从而可以得到 API 返回值
第一个步骤即第九节所讲的内容,ResponseBody 转为 UserBean 的转换规则是通过 Converter 接口来定义的
1
2
3
4
5
6
7
8public interface Converter<F, T> {
//用于将 F 类型转换为 T 类型
@Nullable
T convert(F value) throws IOException;
// ...
}这个过程的转换就发生在 OkHttpCall 中,
enqueue()
方法在拿到 OkHttp 返回的okhttp3.Response
对象后,就通过调用parseResponse()
方法来完成转化为Response<T>
的逻辑,当中就调用了 Converter 接口的convert()
方法,从而得到返回值Response<UserBean>
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
47final class OkHttpCall<T> implements Call<T> {
@Override
public void enqueue(final Callback<T> callback) {
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
}
}
});
}
private final Converter<ResponseBody, T> responseConverter;
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
···
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
//catchingBody 就是 ResponseBody 类型,将其转换为 T 类型
T body = responseConverter.convert(catchingBody);
//然后再将其包装为 Response<T> 类型
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;
}
}
}第二个步骤即第十节所讲的内容, Call 转换为 Observable 的转换规则是通过 CallAdapter 接口来定义的
1
2
3
4
5
6
7
8
9public interface CallAdapter<R, T> {
Type responseType();
//此方法就用于将 Call<R> 转为你希望的目标类型 T,例如:Observable<UserBean>
T adapt(Call<R> call);
//...
}在 CallEnqueueObservable 这个类中,通过自定义回调接口 CallCallback 来发起网络请求,从而拿到在第一个步骤解析完成后的数据,即
Response<UserBean>
对象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
41final class CallEnqueueObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallEnqueueObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override
protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
if (!callback.isDisposed()) {
//自定义回调,发起请求
call.enqueue(callback);
}
}
private static final class CallCallback<T> implements Disposable, Callback<T> {
private final Call<?> call;
private final Observer<? super Response<T>> observer;
private volatile boolean disposed;
boolean terminated = false;
CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
this.call = call;
this.observer = observer;
}
@Override
public void onResponse(Call<T> call, Response<T> response) {
···
//直接将Response<T>传递出去,即 Response<UserBean> 对象
observer.onNext(response);
···
}
···
}
}CallCallback 类同时持有着一个 observer 对象,该 observer 对象实际上又属于 BodyObservable 类。BodyObservable 在拿到了
Response<UserBean>
对象后,如果判断到此次网络请求属于成功状态的话,那么就直接取出 body (即 UserBean)传递出去。因此我们才可以直接拿到目标类型,而不包含任何包装类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
45final class BodyObservable<T> extends Observable<T> {
private final Observable<Response<T>> upstream;
BodyObservable(Observable<Response<T>> upstream) {
this.upstream = upstream;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
upstream.subscribe(new BodyObserver<T>(observer));
}
private static class BodyObserver<R> implements Observer<Response<R>> {
private final Observer<? super R> observer;
private boolean terminated;
BodyObserver(Observer<? super R> observer) {
this.observer = observer;
}
@Override
public void onSubscribe(Disposable disposable) {
observer.onSubscribe(disposable);
}
@Override
public void onNext(Response<R> response) {
if (response.isSuccessful()) {
//如果本次网络请求成功,那么就直接取出 body 传递出去
observer.onNext(response.body());
} else {
terminated = true;
Throwable t = new HttpException(response);
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
···
}
}
十二. Retrofit 对 Android 平台的特殊支持
Retrofit 的内部实现并不需要依赖于 Android 平台,而是可以用于任意的 Java 客户端,Retrofit 只是对 Android 平台进行了特殊实现而已
在构建 Retrofit 对象的时候,我们可以选择传递一个 Platform 对象用于标记调用方所处的平台
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public static final class Builder {
private final Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
···
}Platform 类有两个作用:
判断是否支持 Java 8。这在判断是否支持调用 interface 的默认方法,以及判断是否支持 Optional 和 CompletableFuture 时需要用到。因为 Android 应用如果想要支持 Java 8 的话,是需要在 Gradle 文件中进行主动配置的,且 Java 8 在 Android 平台上目前也支持得并不彻底,所以需要判断是否支持 Java 8 来决定是否启用特定功能
实现 main 线程回调的 Executor。众所周知,Android 平台是不允许在 main 线程上执行耗时任务的,且 UI 操作都需要切换到 main 线程来完成。所以,对于 Android 平台来说,Retrofit 在回调网络请求结果时,都会通过 main 线程执行的 Executor 来进行线程切换
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
81class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
//根据 JVM 名字来判断使用方是否是 Android 平台
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android() //
: new Platform(true);
}
//是否支持 Java 8
private final boolean hasJava8Types;
private final Constructor<Lookup> lookupConstructor;
Platform(boolean hasJava8Types) {
this.hasJava8Types = hasJava8Types;
Constructor<Lookup> lookupConstructor = null;
if (hasJava8Types) {
try {
// Because the service interface might not be public, we need to use a MethodHandle lookup
// that ignores the visibility of the declaringClass.
lookupConstructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
lookupConstructor.setAccessible(true);
} catch (NoClassDefFoundError ignored) {
// Android API 24 or 25 where Lookup doesn't exist. Calling default methods on non-public
// interfaces will fail, but there's nothing we can do about it.
} catch (NoSuchMethodException ignored) {
// Assume JDK 14+ which contains a fix that allows a regular lookup to succeed.
// See https://bugs.openjdk.java.net/browse/JDK-8209005.
}
}
this.lookupConstructor = lookupConstructor;
}
//获取默认的 Executor 实现,用于 Android 平台
Executor defaultCallbackExecutor() {
return null;
}
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
int defaultCallAdapterFactoriesSize() {
return hasJava8Types ? 2 : 1;
}
List<? extends Converter.Factory> defaultConverterFactories() {
return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
}
int defaultConverterFactoriesSize() {
return hasJava8Types ? 1 : 0;
}
// Only called on API 24+.
boolean isDefaultMethod(Method method) {
return hasJava8Types && method.isDefault();
}
// Only called on API 26+.
Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, Object... args)
throws Throwable {
Lookup lookup =
lookupConstructor != null
? lookupConstructor.newInstance(declaringClass, -1 /* trusted */)
: MethodHandles.lookup();
return lookup.unreflectSpecial(method, declaringClass).bindTo(object).invokeWithArguments(args);
}
}
Platform 类只具有一个唯一子类,即 Android 类。其主要逻辑就是重写了父类的
defaultCallbackExecutor()
方法,通过 Handler 来实现在 main 线程执行特定的 Runnable,以此来实现网络请求结果都在 main 线程进行回调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
30static final class Android extends Platform {
Android() {
super(Build.VERSION.SDK_INT >= 24);
}
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
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());
public void execute(Runnable r) {
handler.post(r);
}
}
}Retrofit 有个默认的
CallAdapter.Factory
接口实现类,用于对 API 返回值包装类型是 Call 的情形进行处理。DefaultCallAdapterFactory 会拿到 Platform 返回的 Executor 对象,如果 Executor 对象不为 null 且 API 方法没有标注 SkipCallbackExecutor 注解的话,就使用该 Executor 对象作为一个代理来中转所有的回调操作,以此实现线程切换。这里使用到了装饰器模式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
75final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
···
final Executor executor =
//判断 annotations 是否包含 SkipCallbackExecutor 注解
//有的话说明希望直接在原来的线程进行方法调用,不需要进行线程切换
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
//executor 不为 null 的话就将其作为一个中间代理
//交由 ExecutorCallbackCall 来完成实际的回调操作
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
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;
}
@Override
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
delegate.enqueue(
new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(
() -> {
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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
···
}
}