文章目录
Retrofit 实现一次网络请求流程
- 定义抽象网络请求接口
- new Retrofit对象。配置baseUrl。
- 调用
retrofit.create
函数,生成代理类对象。GitHubService service = retrofit.create(GitHubService.class)
。 - 调用抽象网络接口对象,生成
retrofit2.Call
对象。这个对象的默认实际类型是retrofit2.DefaultCallAdapterFactory.ExecutorCallbackCall
。 - 调用
retrofit2.Call#execute
发起同步网络请求, 或者调用retrofit2.Call#enqueue
发起异步网络请求。
官网wiki
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:retrofit-converters:2.8.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:retrofit-adapters:2.8.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
生成Call<T>
对象 时序图
Retrofit 小的语法规则
- 不支持再网络请求Interface接口中声明泛型。源码位置:
Retrofit#validateServiceInterface(Class<?> service)
- 动态请求参数只能通过
@Query
注解。不支持在GET、POST、HTTP、HEAD....
等注解中通过{ }
定义动态参数,然后在接口函数中通过@Path
注解赋值。 - 网络请求接口Interface,只允许有一个Retrofit的有效注解,不支持多注解情况。
- 网络请求接口Interface接口中的函数禁止void类型的返回值。
- 默认情况下网络请求的异步callback是在主线程中执行的。源码参考:
Platform.Android.MainThreadExecutor
和DefaultCallAdapterFactory#callbackExecutor
设计模式
- 建造者模式
Retrofit.Builder
,RequestFactory.Builder
- 工厂模式。
Converter.Factory
,CallAdapter.Factory
- 适配器模式。
CallAdapter#adapt
,retrofit2.adapter.rxjava3.RxJava3CallAdapter
。适配器内的委托:DefaultCallAdapterFactory.ExecutorCallbackCall#delegate
。 - 动态代理模式。https://blog.csdn.net/followYouself/article/details/120242621
Platform.java
Platform#defaultCallAdapterFactories
函数生成默认CallAdapterPlatform#defaultConverterFactories
函数生成默认ConverterPlatform.Android.MainThreadExecutor
类,默认callback回调在MainLooper中执行。
Platform#Platform 构造函数解析
- Platform构造函数初始化为Android平台。Android平台的判断条件
"Dalvik".equals(System.getProperty("java.vm.name"))
. - 通过
MethodHandles.Lookup
调用非public的interface,调用interface中的default方法。 - 通过反射Lookup的private构造函数,获取Lookup的实例对象。因为默认通过
MethodHandles.lookup()
的静态方法生成Lookup实例对象,此对象是禁止访问私有方法的。 - 一句话解释:
MethodHandles
和Lookup
是一套相比于传统反射框架性能更高更快的反射接口,但传统的反射框架是更通用且开发者更容易实现。 MethodHandles
和Lookup
实现参考Android源码:/Android_Q/libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
Retrofit.Builder.java
Retrofit.Builder#callFactory
默认值是okhttp3.OkHttpClient
。 在Retrofit.Builder#build
函数中赋默认值。可以通过retrofit2.Retrofit.Builder#client
配置Retrofit.Builder#callbackExecutor
默认值是Platform.Android.MainThreadExecutor
。在Retrofit.Builder#build
函数中赋默认值。
RequestFactory.java 网络请求接口解析
okhttp3.Request
对象的构造工厂。用于解析注解和生成request对象。- 自定义的网络请求接口的注解(函数注解和函数参数注解)是在这个类中解析完成的。主要是两个函数:解析函数注解
parseMethodAnnotation
和 解析函数入参注解parseParameter
。 RequestFactory#create
会根据解析的网络接口和相关注解,加上传入的参数,生成请求对象okhttp3.Request
。
RequestFactory.Builder#build函数
- parseMethodAnnotation 解析函数注解。并且使用正则解析出函数注解中的动态参数,例如:
{user}
,解析出user字符串。 - parseParameter 解析函数参数。每个函数参数只允许有一个Retrofit注解。
- 构造RequestFactory实例。
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
private static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*"; // 匹配以大小写字母开始的,含有字母、数字、下划线横线的字符串
// 在PARAM基础上,匹配带{}的字符串。例如{user}、{name}等。并且将PARAM作为子元组。
private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}"); // 两个反斜杠来加大括号来标示匹配 大括号字符串
private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
CallAdapter.java
- 默认的
CallAdapter.Factory
是CompletableFutureCallAdapterFactory
和DefaultCallAdapterFactory
。Retrofit的build函数中调用函数Platform#defaultCallAdapterFactories
添加到List列表。 DefaultCallAdapterFactory
对应的网络接口返回值类型是Call<自定义对象类型>
,CompletableFutureCallAdapterFactory
对应的网络接口返回值类型CompletableFuture<自定义对象类型>
。
DefaultCallAdapterFactory.ExecutorCallbackCall
ExecutorCallbackCall
: 这是调用interface的接口,返回的Call
对象的实际类型。ExecutorCallbackCall
实现了retrofit2.Call
接口,类的内部实现委托到retrofit2.OkHttpCall
对象上。通过OkHttpCall
和okhttp进行网络交互。ExecutorCallbackCall#delegate
这个成员变量,默认的实际类型是retrofit2.OkHttpCall
。
Call<List<Repo>> repos = service.listRepos("octocat"); // ExecutorCallbackCall 类型
OkHttpCall.java
- 这个类是Retrofit与okhttp3交互的核心类。实现了
retrofit2.Call
接口。 - OkHttpCall集成了
RequestFactory
(请求对象工厂),Object[] args
函数入参,okhttp3.Call.Factory callFactory
网络请求工厂(默认OkHttpClient),用callFactory
来生成okhttp3.Call rawCall
,Converter<ResponseBody, T> responseConverter
网络返回对象coverter对象。 enqueue
和execute
网络请求操作,最终都是通过OkHttpCall
委托到okhttp3 上实现。retrofit2.OkHttpCall#rawCall
是实际okhttp3.Call对象。OkHttpCall#createRawCall
函数会调用callFactroy.newCall
生成一个okhttp3.Call
对象,用于发起网络请求。callFactroy
实际是okhttp3.OkHttpClient
对象。okhttp3.OkHttpClient
实现了okhttp3.Call.Factory
接口,实现接口方法okhttp3.Call.Factory#newCall
,用于生成okhttp3.Call
对象。
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;
}
Converter.java
Converter<?, RequestBody> requestBodyConverter
接口的意义是网络请求时,将自定义的?
对象类型转换为okhttp3所需要的RequestBody
类型。Converter<ResponseBody, ?> responseBodyConverter
接口的意义是将okhttp3网络请求返回的ResponseBody
对象转换为?
目标类型。- 默认的
ConverterFactory
类型是BuiltInConverters
,只支持ResponseBody.class
或者Void.class
作为返回值类型。BuiltInConverters
单词字面意思:内部的已经构建好的Converter类,里面包含了多种默认Convert对象。 - 在不添加自定义的
ConverterFactory
时,是无法将网络请求的返回字符串转换为自定义对象的。 - 常用的Factory类型有
GsonConverterFactory
。
一次网络请求的函数执行流程
Call.enqueue(Callback)
-->OkHttpCall#enqueue(Callback)
-->OkHttpCall#createRawCall
-->RequestFactory#create
-->okhttp3.Call#enqueue(Callback)
--> okhttp发起网络请求 --> 回调okhttp3.Callback#onResponse
-->OkHttpCall#parseResponse
--> 调用默认converterBuiltInConverters.BufferingResponseBodyConverter#convert
-->Callback#onResponse
注意点
URL路径:?
问号后不允许动态参数{}
- 动态请求参数只能通过
@Query
注解。不支持在GET、POST、HTTP、HEAD....
等注解中通过{ }
定义动态参数,然后在接口函数中通过@Path
注解赋值。 - 参考:
retrofit2.RequestFactory.Builder#parseHttpMethodAndPath
public interface GitHubService {
@GET("users/{user}/repos?id={id}&nickName={nickName}") // 此处在问号后配置请求参数id和nickName的方式是被禁止的。
Call<List<Repo>> listRepos(@Path("user") String user, @Path("id") String id, @Path("nickName") String nickName);
}
// 源码:retrofit2.RequestFactory.Builder#parseHttpMethodAndPath
// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(method, "URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
网络请求Interface接口的入参不允许多个Retrofit注解
- 函数的入参只允许一个有效Retrofit注解。例如:
@Path
,@Query
不能同时注解一个函数参数。 Multiple Retrofit annotations found, only one allowed
- 参考源码:retrofit2.RequestFactory.Builder#parseParameter
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 =
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;
}
}
}
面向抽象、接口编程
接口 or 抽象类 | 实现 |
---|---|
Call | DefaultCallAdapterFactory.ExecutorCallbackCall, OkHttpCall |
Converter<F, T> | BuiltInConverters.RequestBodyConverter implements Converter<RequestBody, RequestBody>, BuiltInConverters.BufferingResponseBodyConverter implements Converter<ResponseBody, ResponseBody>, retrofit2.converter.gson.GsonRequestBodyConverter implements Converter<T, RequestBody>, retrofit2.converter.gson.GsonResponseBodyConverter implements Converter<ResponseBody, T> |
Converter.Factory | retrofit2.BuiltInConverters, retrofit2.converter.gson.GsonConverterFactory |
CallAdapter<R, T> | DefaultCallAdapterFactory#get new CallAdapter<Object, Call<?>>, retrofit2.adapter.rxjava3.RxJava3CallAdapter implements CallAdapter<R, Object> |
CallAdapter.Factory | retrofit2.DefaultCallAdapterFactory, retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory |
ServiceMethod | HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod |
HttpServiceMethod<ResponseT, ReturnT> | HttpServiceMethod.CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> |
okhttp3.Call | okhttp3.RealCall |
okhttp3.Call.Factory | okhttp3.OkHttpClient |
反射相关方法
Method
getTypeParameters
: 按照声明顺序返回函数中声明的泛型变量,返回值类型是个数组。getGenericParameterTypes
: 获取函数的入参列表。返回Type[]类型的数组。返回值会体现出泛型相关信息。getParameterTypes
: 获取函数的入参列表,返回的是class[] 类型的数组。返回值不会体现泛型相关信息。