Retrofit
MoMo Lv5

retrofit 封装的点

  1. Build 模式 创建网络请求基本配置
  2. 用注解来排列组合成网络请求,以不变应万变
  3. 统一提供Gson解析,提供了可复用,易拓展的数据解析方案
  4. 自定义Executor(handler)完成线程的切换。

什么是Retrofit

Retrofit:A type-safe HTTP client for Android and Java。一个类型安全的 Http 请求的客户端。

底层的网络请求是基于 OkHttp 的,Retrofit 对其做了封装,提供了即方便又高效的网络访问框架。

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
class RetrofitActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//初始化一个Retrofit对象
val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
//创建出GitHubApiService对象
val service = retrofit.create(GitHubApiService::class.java)
//返回一个 Call 对象
val repos = service.listRepos("octocat")
//调用 enqueue 方法在回调方法里处理结果
repos.enqueue(object : Callback<List<Repo>?> {
override fun onFailure(
call: Call<List<Repo>?>,
t: Throwable) {
t.printStackTrace()
}

override fun onResponse(
call: Call<List<Repo>?>,
response: Response<List<Repo>?>) {
"response.code() = ${response.code()}".logE()
}
})

}
}
1
2
3
4
5
6
//自己定义的 API 请求接口
interface GitHubApiService {
@GET("users/{user}/repos")
fun listRepos(@Path("user") user: String?): Call<List<Repo>>
}

源码分析

几个表面上的类:

  • Retrofit: 总揽全局一个类,一些配置,需要通过其内部 Builder类构建,比如 CallAdapter、Converter 等
  • GitHubApiService: 自己写的 API 接口,通过 Retrofit 的 create 方法进行实例化
  • Call: Retrofit 的 Call,是执行网络请求的是一个顶层接口,需要看源码,具体实现类实际是一个 OkHttpCall
  • Callback: 请求结果回调

Call 的 enqueue方法:

1
2
3
4
5
public interface Call extends Cloneable {

void enqueue(Callback callback);

}

这是一个接口,是 GitHubApiService 接口中定义的 listRepos 方法中返回的 Call 对象,现在就要看GitHubApiService 的初始化,以及具体返回的是 Call 对象是谁。

然后重点就要看 retrofit.create(GitHubApiService::class.java) 方法,来看下 GitHubApiService 具体是怎么创建的,以及 Call 对象的实现类

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
27
//Retrofit.java
public <T> T create(final Class<T> service) {
//1
validateServiceInterface(service);
//2
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) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
  • 注释 1:这个方法,就是验证我们定义的 GitHubApiService 是一个接口,且不是泛型接口,并且会判断是否进行方法的 提前验证,为了更好的把错误暴露的编译期,
  • 注释 2 :是一个动态代理的方法,来返回 GitHubApiService 的实例

动态代理的示例

写一个动态代理的Demo

下面是一个 Java 项目,模拟一个 Retrofit 的请求过程

1
2
3
4
5
//模拟 Retrofit,定义 API 请求接口
public interface GitHubApiService {
void listRepos(String user);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ProxyDemo {
//程序的入口方法
public static void main(String[] args) {
//通过动态代理获取 ApiService 的对象
GitHubApiService apiService = (GitHubApiService) Proxy.newProxyInstance(
GitHubApiService.class.getClassLoader(),
new Class[]{GitHubApiService.class},
new InvocationHandler() {
@Override
public Object invoke(
Object proxy,
Method method,
Object[] args) throws Throwable {
System.out.println("method = " + method.getName() + " args = " + Arrays.toString(args));
return null;
}
});

System.out.println(apiService.getClass());
//调用 listRepos 方法
apiService.listRepos("octcat");
}

}

执行 main 方法

当调用 apiService.listRepos("octcat");方法时,打印出来如下结果

1
2
class com.sun.proxy.$Proxy0
method = listRepos args = [octcat]

当调用 listRepos方法的时候,InvocationHandler 的 invoke方法中拦截到了方法,参数等信息。 Retrofit 的原理其实就是拦截到方法、参数,再根据我们在方法上的注解,去拼接为一个正常的OkHttp 请求,然后执行。

日志的第一行,在运行时这个类一个 $Proxy0的类。实际上,在运行期 GitHubApiService 的接口会动态的创建出 实现类也就是这个 $Proxy0类,它大概长下面这个样子,具体可看从一道面试题开始说起 枚举、动态代理的原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class $Proxy0 extends Proxy implements GitHubApiService {

protected $Proxy0(InvocationHandler h) {
super(h);
}

@Override
public void listRepos(String user) {

Method method = Class.forName("GitHubApiService").getMethod("listRepos", String.class);

super.h.invoke(this, method, new Object[]{user});
}
}

在调用 listRepos方法的时候,实际上调用的是 InvocationHandler 的 invoke 方法。

总结

  • 在 ProxyDemo 代码运行中,会动态创建 GitHubApiService 接口的实现类,作为代理对象,执行InvocationHandler 的 invoke 方法。
  • 动态指的是在运行期,而代理指的是实现了GitHubApiService 接口的具体类,实现了接口的方法,称之为代理
  • 本质上是在运行期,生成了 GitHubApiService 接口的实现类,调用了 InvocationHandler 的 invoke方法。

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
27
28
//Retrofit.java
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),//1
new Class<?>[] {service},//2
new InvocationHandler() {//3
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.
//4
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
//5
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}

  • 注释 1:获取一个 ClassLoader 对象

  • 注释 2:GitHubApiService 的字节码对象传到数组中去,也即是我们要代理的具体接口。

  • 注释 3:InvocationHandler 的 invoke 是关键,从上面动态代理的 Demo 中,我们知道,在GitHubApiService声明的 listRepos方法在调用时,会执行 InvocationHandler 的 invoke的方法体。

  • 注释 4:因为有代理类的生成,默认继承 Object 类,所以如果是 Object.class 走,默认调用它的方法

  • 注释 5:如果是默认方法(比如 Java8 ),就执行 platform 的默认方法。 否则执行 loadServiceMethod 方法的 invoke 方法

loadServiceMethod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Retrofit.java
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

ServiceMethod<?> loadServiceMethod(Method method) {
//1
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;

synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//2
result = ServiceMethod.parseAnnotations(this, method);
//3
serviceMethodCache.put(method, result);
}
}
return result;
}
  • 注释 1:从 ConcurrentHashMap 中取一个 ServiceMethod 如果存在直接返回

  • 注释 2:通过 ServiceMethod.parseAnnotations(this, method);方法创建一个 ServiceMethod 对象

  • 注释 3:用 Map 把创建的 ServiceMethod 对象缓存起来,因为我们的请求方法可能会调用多次,缓存提升性能。

ServiceMethod.parseAnnotations

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
//ServiceMethod.java
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
...
//1
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}


//HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;

//1
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
//2
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);
}
}
  • 注释 1:callFactory 的值是从 Retrofit 这个对象拿到的

  • 注释 2:如果不是 Kotlin 的挂起函数,返回是的 CallAdapted 对象

返回的是一个 HttpServiceMethod对象

HttpServiceMethod.invoke

1
2
3
4
5
6
7
8
//HttpServiceMethod.java
@Override
final @Nullable ReturnT invoke(Object[] args) {
//1
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
//2
return adapt(call, args);
}
  • 注释 1:创建了一个Call对象,是 OkHttpCall —— 在 GitHubApiService 这个接口声明的 Call 对象

  • 注释 2:是一个 adapt 方法,在不使用 Kotlin 协程的情况下,其实调用的是子类 CallAdapted 的 adapt

OkHttpCall的enqueue方法

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
//OkHttpCall.java
@Override
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");

//1
okhttp3.Call call;
Throwable failure;

synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;

call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
//2
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}

if (failure != null) {
callback.onFailure(this, failure);
return;
}

if (canceled) {
call.cancel();
}

//3
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
//4
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}

try {
//5
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 {
//6
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
  • 注释 1:声明一个 okhttp3.Call 对象,用来进行网络请求

  • 注释 2:给 okhttp3.Call 对象进行赋值,下面会具体看代码,如何创建了一个 okhttp3.Call 对象

  • 注释 3:调用 okhttp3.Call 的 enqueue 方法,进行真正的网络请求

  • 注释 4:解析响应,下面会具体看代码

  • 注释 5:成功的回调

  • 注释 6:失败的回调

okhttp3.Call 对象是怎么创建的

看下 call = rawCall = createRawCall();方法

1
2
3
4
5
6
7
8
9
10
11
//OkHttpCall.java
private final okhttp3.Call.Factory callFactory;

private okhttp3.Call createRawCall() throws IOException {
//1 callFactory是什么
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}

通过 callFactory 创建的(callFactory应该是 OkHttpClient),看一下 callFactory 的赋值过程

1
2
3
4
5
6
7
8
9
10
11
12
//OkHttpCall.java
OkHttpCall(
RequestFactory requestFactory,
Object[] args,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory;
this.args = args;
//通过 OkHttpCall 构造直接赋值
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}

在 OkHttpCall 构造中直接赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//HttpServiceMethod.java
private final okhttp3.Call.Factory callFactory;

@Override
final @Nullable ReturnT invoke(Object[] args) {
//在 OkHttpCall 实例化时赋值, callFactory 是 HttpServiceMethod 的成员变量
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}

//callFactory 是在 HttpServiceMethod 的构造中赋值的
HttpServiceMethod(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
//通过 HttpServiceMethod 构造直接赋值
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
1
static final class CallAdapted extends HttpServiceMethod {}

CallAdapted 是 HttpServiceMethod 的子类,会调用 adapt方法进行 CallAdapter 的转换,我们后面会详细看。

Builder类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static final class Builder {
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);
}

}

callFactory 实际是一个 OkHttpClient 对象,也就是 OkHttpClient 创建了一个 Call 对象

在创建okhttp3.Call 对象的 callFactory.newCall(requestFactory.create(args));方法中的 requestFactory.create(args)方法会返回一个 Request 的对象,这个我们也会在下面看是如何构造一个 OkHttp 的 Request 请求对象的。

请求注解参数是怎么解析的

ServiceMethod.parseAnnotations(this, method)

1
2
3
4
5
6
7
8
//ServiceMethod.java
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//1
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
...
//2
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
  • 注释 1:通过 RequestFactory 解析注解,然后返回 RequestFactory 对象

  • 注释 2:把 RequestFactory 对象往 HttpServiceMethod 里面传递,下面会具体看 RequestFactory 对象具体干什么用了?

RequestFactory.parseAnnotations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//RequestFactory.java
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
//看build方法
return new Builder(retrofit, method).build();
}

//build方法
RequestFactory build() {
//1
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}

....

return new RequestFactory(this);
}
}

遍历 GitHubApiService 这个 API 接口上定义的方法注解,然后解析注解

parseMethodAnnotation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//RequestFactory.java
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
}
...
else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
}
....
else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}

RequestFactory 这个类还有 parseParameterparseParameterAnnotation这个就是解析方法参数声明上的具体参数的注解

分析方法上的各个注解,方法参数上的注解,最后返回 RequestFactory 对象,给下面使用。

RequestFactory 对象返回出去,具体干嘛用了?

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
//ServiceMethod.java
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//解析注解参数,获取 RequestFactory 对象
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
//把 RequestFactory 对象传给 HttpServiceMethod
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

//注意换类了
//HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {

...

okhttp3.Call.Factory callFactory = retrofit.callFactory;
//不是 Kotlin 的挂起函数
if (!isKotlinSuspendFunction) {
//把requestFactory传给 CallAdapted
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
....
}

//HttpServiceMethod.java
//CallAdapted 是 HttpServiceMethod 的内部类也是 HttpServiceMethod 的子类
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
//这里把 requestFactory 传给 super 父类的构造参数里了,也就是 HttpServiceMethod
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}

//HttpServiceMethod.java
HttpServiceMethod(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter) {
// HttpServiceMethod 的 requestFactory 成员变量保存这个 RequestFactory 对象
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}

//因为会调用 HttpServiceMethod 的 invoke 方法
//会把这个 RequestFactory 对象会继续传递给 OkHttpCall 类中
//注意换类了
//OkHttpCall.java
OkHttpCall(
RequestFactory requestFactory,
Object[] args,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, T> responseConverter) {
//给 OkHttpCall 的requestFactory成员变量赋值
this.requestFactory = requestFactory;
this.args = args;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}

经过层层传递 RequestFactory 这个实例终于是到了 HttpServiceMethod 类中,最终传到了 OkHttpCall 中,那这个 RequestFactory 对象在什么时候使用呢? RequestFactory 会继续在OkHttpCall中传递,因为 OkHttpCall 才是进行请求的。

在OkHttpCall的 创建 Call 对象时

1
2
3
4
5
6
7
8
9
//OkHttpCall.java
private okhttp3.Call createRawCall() throws IOException {
//1
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
  • 注释 1:调用了 requestFactory.create(args)

注意:此时的RequestFactory的各个成员变量在解析注解那一步都赋值了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//RequestFactory.java
okhttp3.Request create(Object[] args) throws IOException {
...
RequestBuilder requestBuilder =
new RequestBuilder(
httpMethod,
baseUrl,
relativeUrl,
headers,
contentType,
hasBody,
isFormEncoded,
isMultipart);
...
return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
}

最终 requestFactory 的值用来构造 okhttp3.Request 的对象

请求响应结果是如何解析的

比如我们在构造 Retrofit 的时候加上 addConverterFactory(GsonConverterFactory.create())这行代码,我们的响应结果是如何通过 Gson 直接解析成数据模型的?

在 OkHttpCall 的 enqueue方法中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//OkHttpCall.java
@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 {
//1 解析响应
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
}
...
});
}
  • 注释 1:通过 parseResponse解析响应返回给回调接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//OkHttpCall.java
private final Converter<ResponseBody, T> responseConverter;

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();

...

ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
//1 通过 responseConverter 转换 ResponseBody
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;
}
}
  • 注释 1:通过 responseConverter 调用 convert方法

首先那看 responseConverter 是什么以及赋值的过程,然后再看 convert方法

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
//OkHttpCall.java
private final Converter<ResponseBody, T> responseConverter;

OkHttpCall(
RequestFactory requestFactory,
Object[] args,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory;
this.args = args;
this.callFactory = callFactory;
//在构造中赋值
this.responseConverter = responseConverter;
}

// OkHttpCall 在 HttpServiceMethod 类中实例化
//注意换类了
//HttpServiceMethod.java
private final Converter<ResponseBody, ResponseT> responseConverter;

HttpServiceMethod(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
//在构造中赋值
this.responseConverter = responseConverter;
}

//HttpServiceMethod 在子类 CallAdapted 调用 super方法赋值
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
//在CallAdapted中调用super赋值
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}

继续看 CallAdapted 的初始化中 responseConverter 的赋值过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
...
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);

//1 实例化responseConverter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);

okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
//2 CallAdapted的实例化赋值
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
...
}

继续跟代码 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
33
34
35
//HttpServiceMethod.java
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
//调用的是 retrofit的方法
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.java
final List<Converter.Factory> converterFactories;

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

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
...
//1 从 converterFactories工厂中遍历取出
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;
}
}
...
}
  • 注释 1:从 converterFactories 遍历取出一个来调用 responseBodyConverter 方法,注意根据 responseType 返回值类型来取到对应的 Converter,如果不为空,直接返回此 Converter 对象

converterFactories 这个对象的赋值过程

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
//Retrofit.java
final List<Converter.Factory> converterFactories;

Retrofit(
okhttp3.Call.Factory callFactory,
HttpUrl baseUrl,
List<Converter.Factory> converterFactories,
List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor,
boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
//通过 Retrofit 的构造赋值,Retrofit的 初始化是通过内部 Builder 类的build方法
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}

//Retrofit.java 内部类 Builder 类的build方法
//Builder.java
public Retrofit build() {

...
// Make a defensive copy of the converters.
//1
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
//2
converterFactories.add(new BuiltInConverters());
//3
converterFactories.addAll(this.converterFactories);
//4
converterFactories.addAll(platform.defaultConverterFactories());

return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
  • 注释 1:初始化 converterFactories 这个 list

  • 注释 2:添加默认的构建的转换器,其实是 StreamingResponseBodyConverter 和 BufferingResponseBodyConverter

  • 注释 3:就是自己添加的转换配置 addConverterFactory(GsonConverterFactory.create())

1
2
3
4
5
//Retrofit.java 内部类 Builder.java
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
  • 注释 4:如果是 Java8 就是一个 OptionalConverterFactory 的转换器否则就是一个空的

是怎么找到GsonConverterFactory来调用 Gson 的 convert方法的呢?
在遍历converterFactories时会根据 responseType来找到对应的转换器。

CallAdapter的替换过程

使用 RxJava 进行网络请求

怎么转成 RxJava

比如:我们在初始化一个Retrofit时加入 addCallAdapterFactory(RxJava2CallAdapterFactory.create())这行

1
2
3
4
5
6
7
//初始化一个Retrofit对象
val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com/")
//加入 RxJava2CallAdapterFactory 支持
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()

加入 RxJava2 的配置支持后,把 RxJava2CallAdapterFactory 存到 callAdapterFactories 这个集合中

1
2
3
4
interface GitHubApiService {
@GET("users/{user}/repos")
fun listReposRx(@Path("user") user: String?): Single<Repo>
}

我们就可以这么请求接口了

1
2
3
4
5
6
7
8
9
10
//创建出GitHubApiService对象
val service = retrofit.create(GitHubApiService::class.java)
service.listReposRx("octocat")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ repo ->
"response name = ${repo[0].name}".logE()
}, { error ->
error.printStackTrace()
})

我们可以在自己定义的 API 接口中直接返回一个 RxJava 的 Single 对象的,来进行操作了。

我们下面就来看下是如何把请求对象转换成一个 Single 对象的

1
2
3
4
5
//Retrofit.java 内部类 Builder.java
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}

把 RxJava2CallAdapterFactory 存到了callAdapterFactories 这个 list 中了。

CallAdapter是如何被赋值过程

HttpServiceMethod的 parseAnnotations 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {

....
//1
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);

okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
//2
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
...
}
  • 注释 1:初始化 CallAdapter

  • 注释 2:给 CallAdapted 中的 callAdapter 变量赋值,然后调用它的 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
//HttpServiceMethod.java
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
//调用retrofit的callAdapter方法
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}

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

public CallAdapter<?, ?> nextCallAdapter(
@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {

...

//遍历 callAdapterFactories
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
//是具体CallAdapterFactory的 get 方法
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
}

遍历 callAdapterFactories 根据 returnType类型 来找到对应的 CallAdapter 返回

比如:我们在 GitHubApiService 的 returnType 类型为 Single,那么返回的就是 RxJava2CallAdapterFactory 所获取的 CallAdapter

1
2
3
4
interface GitHubApiService {
@GET("users/{user}/repos")
fun listReposRx(@Path("user") user: String?): Single<Repo>
}

RxJava2CallAdapterFactory的 get方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//RxJava2CallAdapterFactory.java
@Override public @Nullable 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;
//当前是Single类型
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
...
//返回 RxJava2CallAdapter对象,isSingle参数为 true
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}

返回的是 RxJava2CallAdapter 对象,并且根据 rawType 判断当前是个什么类型

看下 RxJava2CallAdapter 的 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
//RxJava2CallAdapter.java
@Override public Object adapt(Call<R> call) {
//1 把Call包装成一个Observable对象
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);
}
//2
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return RxJavaPlugins.onAssembly(observable);
}
  • 注释 1:把 Call 包装成一个 Observable 对象

  • 注释2:如果是 Single 则调用 observable.singleOrError();方法

Retrofit 如何支持 Kotlin 协程的 suspend 挂起函数的?

Kotlin 协程请求网络的 Demo

添加依赖

1
2
3
4
5
6
7
def kotlin_coroutines = '1.3.7'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines"

implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'

定义请求接口,写一个挂起函数

1
2
3
4
5
interface GitHubApiService {
//使用 Kotlin 协程 ,定义一个挂起函数
@GET("users/{user}/repos")
suspend fun listReposKt(@Path("user") user: String?): List<Repo>
}

请求接口

1
2
3
4
5
6
7
8
9
10
11
12
13
//创建出GitHubApiService对象
val service = retrofit.create(GitHubApiService::class.java)
//lifecycle提供的协程的Scope,因为 suspend 函数需要运行在协程里面
lifecycleScope.launchWhenResumed {
try {
val repo = service.listReposKt("octocat")
"response name = ${repo[0].name}".logE()
} catch (e: Exception) {
e.printStackTrace()
//出错逻辑
//ignore
}
}

Kotlin 协程的挂起函数的准备工作

1
2
3
suspend fun test(name: String) {

}

我们通过 Android Studio 再带的工具,如下图:把 Kotlin 方法转成 Java 方法 image

结果如下

1
2
3
4
5
6
public final class SuspendKt {
@Nullable
public static final Object test(@NotNull String name, @NotNull Continuation $completion) {
return Unit.INSTANCE;
}
}

suspend 的关键字,变成了 test 方法的一个Continuation参数,且为最后一个参数

1
2
3
4
5
@SinceKotlin("1.3")
public interface Continuation<in T> {
public val context: CoroutineContext
public fun resumeWith(result: Result<T>)
}

Retrofit 是怎么支持 Kotlin 协程的挂起函数的。

最终会调用到 HttpServiceMethod 的 parseAnnotations 方法

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
//HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
//1 获取 isKotlinSuspendFunction 的值,这个会在下面具体分析
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;

Annotation[] annotations = method.getAnnotations();
Type adapterType;
//2 如果是 Kotlin 挂起函数
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType =
Utils.getParameterLowerBound(
0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {

responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
//3 continuationWantsResponse 赋值为 true
continuationWantsResponse = true;
} else {

}

adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}

Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);

okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);

} else if (continuationWantsResponse) {
//4 返回 SuspendForResponse 它是 HttpServiceMethod的子类
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {

return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
  • 注释 1:获取 isKotlinSuspendFunction 的值,这个会在下面具体分析

  • 注释 2:如果是 Kotlin 挂起函数,进入此代码块

  • 注释 3:把 continuationWantsResponse 赋值为 true

  • 注释 4:返回 SuspendForResponse 它是 HttpServiceMethod 的子类,然后看它的 adapt方法,

requestFactory.isKotlinSuspendFunction 赋值

requestFactory 这个类,是解析注解的

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
//RequestFactory.java
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction =
//1 遍历解析参数的注解,就是 @Path @Query @Field 等注解,具体就不看了,不是协程的重点
parseParameterAnnotation(p, parameterType, annotations, annotation);

if (annotationAction == null) {
continue;
}

if (result != null) {
throw parameterError(
method, p, "Multiple Retrofit annotations found, only one allowed.");
}

result = annotationAction;
}
}

if (result == null) {
//2 如果是协程 ,其实比的就是最后一个值
if (allowContinuation) {
try {
//3 判断参数类型是 Continuation,这个接口,前面在 10.2 小节写 Demo 时提过
if (Utils.getRawType(parameterType) == Continuation.class) {
// 4 isKotlinSuspendFunction 赋值为 true
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, "No Retrofit annotation found.");
}

return result;
}
  • 注释 1:遍历解析参数的注解,就是 @Path @Query @Field 等注解,具体就不看了,不是协程的重点

  • 注释 2:如果是协程 ,其实比的就是最后一个值

  • 注释 3:判断参数类型是 Continuation,这个接口,前面在 10.2 小节写 Demo 时提过

  • 注释 4:isKotlinSuspendFunction 赋值为 true

如果isKotlinSuspendFunction 为 true 时,返回就是 SuspendForResponse 类

SuspendForResponse类

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
static final class SuspendForResponse<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;

SuspendForResponse(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, Call<ResponseT>> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}

@Override
protected Object adapt(Call<ResponseT> call, Object[] args) {
//1
call = callAdapter.adapt(call);

//noinspection unchecked Checked by reflection inside RequestFactory.
//2
Continuation<Response<ResponseT>> continuation =
(Continuation<Response<ResponseT>>) args[args.length - 1];

// See SuspendForBody for explanation about this try/catch.
try {
//3
return KotlinExtensions.awaitResponse(call, continuation);
} catch (Exception e) {
//4
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
}
  • 注释 1:调用 callAdapter 代理 call 方法

  • 注释 2:取出最后一个参数,强转成 Continuation 类型,想想我们写的 Demo

  • 注释 3:Call 的扩展函数(Kotlin 的写法)下面具体看下 awaitResponse

  • 注释 4:出现异常,抛出异常。所以要在代码中,要主动 try catch,来处理错误

Call的扩展函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//KotlinExtensions.kt
suspend fun <T> Call<T>.awaitResponse(): Response<T> {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
//调用 Call的enqueue方法
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
//成功回调
continuation.resume(response)
}

override fun onFailure(call: Call<T>, t: Throwable) {
//失败回调
continuation.resumeWithException(t)
}
})
}
}

注解

注解(Annotation),也叫元数据(Metadata),是Java5的新特性,JDK5引入了Metadata很容易的就能够调用Annotations。注解与类、接口、枚举在同一个层次,并可以应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中,用来对这些元

注解通过反射获取

  1. 首先通过 Class 对象的 isAnnotationPresent()方法判断它是否应用了某个注
  2. 然后通过 getAnnotation()方法来获取 Annotation 对象
  3. 或者是 getAnnotations()方法 返回注解到这个元素上的所有注解

定义该注解的生命周期-@Retention
RetentionPolicy.SOURCE:在源文件中有效,被编译器丢弃,用来提示开发者RetentionPolicy.CLASS:在class文件有效,被虚拟机丢弃,用于自动生成代码RetentionPolicy.RUNTIME:运行时有效,常用于自动注入

注解的语法与定义形式

  1. 以@interface关键字定义
  2. 注解包含成员,成员以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。
  3. 成员赋值是通过@Annotation(name=value)的形式。
  4. 注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。
1
2
3
4
5
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.ANNOTATION_TYPE } )
public @interface Target {
ElementType[] value();
}
  1. 元注解@Retention,成员value的值为RetentionPolicy.RUNTIME。
  2. 元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE
  3. 成员名称为value,类型为ElementType[]

另外需要注意,如果成员名称是value,在赋值过程中可以简写。如果成员类型为数组,但是只赋值一个元素,则也可以简写。如上面的简写形式为:

1
2
3
4
5
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}

注解的运用场景限定

@Documented

标记注解,用于描述其它类型的注解应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。

1
2
3
4
5
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

@Inherited

标记注解,允许子类继承父类的注解

1
2
3
4
5
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

@Retention

指Annotation被保留的时间长短,标明注解的生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public enum RetentionPolicy {
/**
* 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃.
* 这意味着:Annotation仅存在于编译器处理期间,编译器处理完之后,该Annotation就没用了
*/
SOURCE,

/**
* 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期.
*/
CLASS,

/**
* 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,
* 保存到class对象中,可以通过反射来获取
*/
RUNTIME
}
1
2
3
4
5
6
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}

@Target

标明注解的修饰目标,共有

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
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}

// ElementType取值
public enum ElementType {
/** 类、接口(包括注解类型)或枚举 */
TYPE,
/** field属性,也包括enum常量使用的注解 */
FIELD,
/** 方法 */
METHOD,
/** 参数 */
PARAMETER,
/** 构造函数 */
CONSTRUCTOR,
/** 局部变量 */
LOCAL_VARIABLE,
/** 注解上使用的元注解 */
ANNOTATION_TYPE,
/** 包 */
PACKAGE
}

总结

什么是动态代理?

  • 动态 指的是在运行期
  • 代理 指的是实现了某个接口的具体类,称之为代理,会调用了 InvocationHandler 的 invoke方法。

Retrofit 中的动态代理:

  • 在代码运行中,会动态创建 GitHubApiService 接口的实现类,作为代理对象,代理接口的方法
  • 在我们调用GitHubApiService 接口的实现类的 listRepos方法时,会调用了 InvocationHandler 的 invoke方法。
  • 本质上是在运行期,生成了 GitHubApiService 接口的实现类,调用了 InvocationHandler 的 invoke方法。

动态代理的示例

整个请求的流程是怎样的

  • 在调用 GitHubApiService 接口的 listRepos方法时,会调用 InvocationHandler 的 invoke方法
  • 然后执行 loadServiceMethod方法并返回一个 HttpServiceMethod 对象并调用它的 invoke方法
  • 然后执行 OkHttpCall的 enqueue方法
  • 本质执行的是 okhttp3.Call 的 enqueue方法
  • 当然这期间会解析方法上的注解,方法的参数注解,拼成 okhttp3.Call 需要的 okhttp3.Request 对象
  • 然后通过 Converter 来解析返回的响应数据,并回调 CallBack 接口

底层是如何用 OkHttp 请求的?

OkHttpCall的enqueue方法

方法上的注解是什么时候解析的,怎么解析的?

  • 在 ServiceMethod.parseAnnotations(this, method); 方法中开始的
  • 具体内容是在 RequestFactory 类中,进行解析注解的
  • 调用 RequestFactory.parseAnnotations(retrofit, method); 方法实现的

请求注解参数是怎么解析的

Converter 的转换过程,怎么通过 Gson 转成对应的数据模型的?

  • 通过成功回调的 parseResponse(rawResponse);方法开始
  • 通过 responseConverter 的 convert 方法
  • responseConverter 是通过 converterFactories 通过遍历,根据返回值类型来使用对应的 Converter 解析

请求响应结果是如何解析的

CallAdapter 的替换过程,怎么转成 RxJava 进行操作的?

  • 通过配置 addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 在 callAdapterFactories 这个 list 中添加 RxJava2CallAdapterFactory
  • 如果不是 Kotlin 挂起函数最终调用的是 CallAdapted 的 adapt方法
  • callAdapter 的实例是通过 callAdapterFactories 这个 list 通过遍历,根据返回值类型来选择合适的CallAdapter

CallAdapter的替换过程

如何支持 Kotlin 协程的 suspend 挂起函数的?

  • 通过 RequestFactory 解析方法上的参数值来判断是不是一个挂起函数,并把 isKotlinSuspendFunction 变量置为 true
  • 根据 isKotlinSuspendFunction 这个变量来判断响应类型是否是 Response 类型,然后把continuationWantsResponse 置为 true
  • 根据 continuationWantsResponse 这个变量,来返回 SuspendForResponse 对象
  • 并调用 SuspendForResponse 的 invoke 方法
  • 通过 Call 的扩展函数,来调用 Call 的 enqueue方法
  • 通过协程来返回
Powered by Hexo & Theme Keep
Unique Visitor Page View