文章目录
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[] 类型的数组。返回值不会体现泛型相关信息。

1941

被折叠的 条评论
为什么被折叠?



