Retrofit源码阅读
1. Retrofit的简介与使用
1.1 Retrofit的简介
Retrofit主要是对OkHttp做了一层封装,利用注解的方式使得接口请求更简单,灵活的使用Converter可使得请求数据与解析一体化更方便,Android端还会自动将回调执行在主线程可以直接修改UI,新版的Retrofit还集成了Kotlin协程,更是利用协程解决了接口请求回调地狱的问题。
1.2 Retrofit的使用
- 添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
- 定义接口请求和解析的实体类
/**
* 接口服务
* @author LTP 2023/7/18
*/
interface Api {
/** 获取首页banner数据(协程方式返回无包装的实体) */
@GET("banner/json")
suspend fun getBanner(): ApiResponse<List<Banner>>
/** 获取首页banner数据(使用协程返回Response包装的实体) */
@GET("banner/json")
suspend fun getBanner2(): Response<ApiResponse<List<Banner>>>
/** 获取首页banner数据(普通方式返回Call包装的实体) */
@GET("banner/json")
fun getBanner3(): Call<ApiResponse<List<Banner>>>
}
/**
* 接口返回外层封装实体
*
* @author LTP 2022/3/22
*/
data class ApiResponse<T>(
val data: T,
val errorCode: Int,
val errorMsg: String
)
/**
* 轮播图实体
*
* @author LTP 2022/3/22
*/
data class Banner(
var desc: String = "",
var id: Int = 0,
var imagePath: String = "",
var isVisible: Int = 0,
var order: Int = 0,
var title: String = "",
var type: Int = 0,
var url: String = ""
)
- 创建Retrofit对象,开启请求
/**
* Retrofit请求网络测试类
* @author LTP 2023/7/17
*/
class RetrofitUnitTest {
/**创建retrofit对象 */
private val retrofit = Retrofit.Builder().baseUrl("https://www.wanandroid.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
@Test
fun getBanner() {
val api = retrofit.create(Api::class.java)
// runBlocking启动的协程会阻塞线程
runBlocking {
val response = api.getBanner()
println(response)
val response2 = api.getBanner2()
println(response2.body())
}
// Retrofit异步请求
api.getBanner3().enqueue(object : Callback<ApiResponse<List<Banner>>> {
override fun onResponse(
call: Call<ApiResponse<List<Banner>>>,
response: Response<ApiResponse<List<Banner>>>
) {
println(response)
}
override fun onFailure(call: Call<ApiResponse<List<Banner>>>, t: Throwable) {
}
})
// 异步请求需要阻塞住主线程以等待请求完毕
Thread.sleep(5000)
// Retrofit同步请求
val response = api.getBanner3().execute()
println(response)
}
}
- 整个过程非常简单舒适,当然,Retrofit还可以进行更多的复杂操作,如配置请求头、请求提、表单提交等,可以直接看官网,这里就不再赘述了,直接看下整个请求过程
2. 源码解析
2.1 Retrofit对象的创建
- 创建方式为:Retrofit.Builder().build(),一看就是Builder设计模式了,先看下Retrofit中的几个成员变量
public final class Retrofit {
/** 主要用来缓存请求方法 */
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
/** okhttp3.Call.Factory接口的实现类(OkHttpClient是唯一实现类) */
final okhttp3.Call.Factory callFactory;
/** 服务器根路径(当包含路径时必须以/结尾) */
final HttpUrl baseUrl;
/** 请求响应数据解析器集合(如GsonConverterFactory.create()) */
final List<Converter.Factory> converterFactories;
/** 网络请求适配器工厂集合,用于放置我们的网络请求适配器工厂(网络请求适配器:把我们的call对象转换成其他类型)
* 如RxJavaCallAdapterFactory
*/
final List<CallAdapter.Factory> callAdapterFactories;
/** 用于回调执行(如Android中是MainThreadExecutor即主线程执行) */
final @Nullable Executor callbackExecutor;
/** 标志位,控制 Retrofit 是否立即验证 HTTP 请求和响应,以确保它们的正确性和完整性 */
final boolean validateEagerly;
...
- 直接看Builder模式最关键的方法build(),主要是针对成员进行组装判断,最终构造Retrofit对象
// Retrofit.java
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 设置OkHttp中Call的工厂类(OkHttpClient是唯一实现类)
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
// 没有设置的话使用默认的OkHttpClient对象
callFactory = new OkHttpClient();
}
// 执行请求回调的对象,Android中defaultCallbackExecutor是MainThreadExecutor即主线程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 网络请求适配器工厂集合
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 数据转换器工厂集合(网络请求返回数据解析)
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 先添加内置转换器工厂BuiltInConverters,主要包含一些基本类型(如
// String:将响应数据转换为 String 类型、Integer、Long、Float、Double、Boolean、Character)的转换
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
- 着重看下几个注意的点
baseUrl中包含路径时必须以/结尾
public Builder baseUrl(URL baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl.toString()));
}
public Builder baseUrl(String baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
public Builder baseUrl(HttpUrl baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
// 当baseUrl是一个域名加路径但路径最后一个字符不是以'/'结尾抛异常
// 如https://www.wanandroid.com/api不行,必须为https://www.wanandroid.com/api/
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
platform.defaultCallbackExecutor()
中platform是在Builder构造中通过Platform.get()获取的,看下这个Platform
类
/** 平台类(Android平台和Java平台) */
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
/**
* 判断当前平台是Android还是Java
* @return 平台类型
*/
private static Platform findPlatform() {
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android() //
: new Platform(true);
}
...
/** Android平台 */
static final class Android extends Platform {
Android() {
super(Build.VERSION.SDK_INT >= 24);
}
/** Android平台下默认的callbackExecutor是MainThreadExecutor,即主线程 */
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
...
static final class MainThreadExecutor implements Executor {
// 子线程到主线程还是通过Handler来切换线程的
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
}
}
- addConverterFactory:添加响应数据转换工厂,在build()方法中已添加默认的
BuiltInConverters
转换器,可针对一些常见类型(如服务器接口返回String、Integer、Long、Float、Double、Boolean、Character)进行转换,但通常服务器返回的是更复杂的数据类型,譬如Json数据、xml数据,而针对这种数据,Retrofit也提供了通用的一些转换插件(如converter-gson、converter-simplexml、converter-moshi等),这里以converter-gson为例
private val retrofit = Retrofit.Builder().baseUrl("https://www.wanandroid.com")
.addConverterFactory(GsonConverterFactory.create()) // 添加GsonConverter
.build()
- 在covert-gson插件中看下GsonConverterFactory.create()方法
public final class GsonConverterFactory extends Converter.Factory {
public static GsonConverterFactory create() {
return create(new Gson());
}
@SuppressWarnings("ConstantConditions")
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
- 主要是
继承了Converter.Factory抽象类
,实现请求和响应转换方法,当然你也可以通过继承Converter.Factory抽象类来实现自定义请求响应转换器
2.2 网络请求
2.2.1 retrofit.create()
- 从关键代码retrofit.create(Api::class.java)方法看起
// Retrofit.java
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// 如果方法是Object类中的方法,直接正常调用即可,无需代理
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
// 这里判断了是否是默认方法(java8接口新增了默认方法),不是就调用loadServiceMethod
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
- 这是一个典型的动态代理设计模式,代理返回一个Api实现类,调用api.getBanner就会去执行
invoke
方法,直接看invoke方法,忽略掉特殊情况(Object类的方法、java8接口的默认方法),最后调用的是loadServiceMethod(method).invoke(args)
,其中method表示getBanner接口方法
// Retrofit.java
/**
* 加载数据请求服务的方法(由于解析会用到反射,加载后会存入缓存提升性能)
* @param method Method
* @return 请求服务的方法
*/
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.parseAnnotations(this, method)
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 这里会创建一个封装了OkHttp.Request的请求对象
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);
}
RequestFactory
是对OkHttp.Request请求的封装,后面再深入源码,先一路深入,看下HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)这个方法
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
/** 检查接口方法上的注释,以构造一个可重复使用的HTTP服务方法。需要通过反射,所以需要使用缓存进行重用 */
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
/** 是否是协程调用 */
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
/** 协程返回是否是Response包装实体 */
boolean continuationWantsResponse = false;
/** 协程返回是否是null */
boolean continuationBodyNullable = false;
// 解析方法上的所有注解
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType =
Utils.getParameterLowerBound(
0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// 这里判断协程的返回是否是一个Response,即判断是一个Response包装实体
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
// 获取方法返回类型
adapterType = method.getGenericReturnType();
}
// 获取CallAdapter,分析可发现这里最后返回的是DefaultCallAdapterFactory
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
// 返回类型的校验
// 返回类型不能为okhttp3.Response类型
if (responseType == okhttp3.Response.class) {
throw methodError(
method,
"'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
// 返回类型不能是Response,必须要包含泛型才行,类似于Response<String>
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.");
}
// 获取Convert对象,自带的是BuiltInConverters,我们传入了GsonConverterFactory
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
// 获取一个okhttp3.Call.Factory对象,其实就是OkHttpClient对象
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 不是Kotlin协程的suspend方法
// 返回一个新建的CallAdapted对象,传入requestFactory, callFactory, responseConverter, callAdapter
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
// 协程返回类型是Response<T>
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
// 协程返回类型是 T
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
- 直接看最后的返回,不是协程时返回的是
CallAdapted
对象,协程时当请求suspend函数返回的是Response时,返回SuspendForResponse
对象,协程直接返回实体T时返回SuspendForBody
- 参数中
requestFactory
,callFactory
,responseConverter
,callAdapter
均比较重要后面再逐个分析 - 追了这么久的返回值,最开始是从loadServiceMethod(method).invoke(args)调用的,loadServiceMethod(method)返回的是CallAdapted/SuspendForResponse/SuspendForBody,所以最后分别是这三个对象调用了invoke(),先看不是协程时callAdapted.invoke()
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
- 没看到有invoke()方法,向他的父类继续寻找
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
...
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
...
}
- 父类的invoke()调用了抽象方法adapt(call,args),这个call是一个
OkHttpCall
本质上是okhttp3.Call的扩展,先放着后面再探讨,adapt这个抽象方法再在子类CallAdapted中被重写,所以最终会执行CallAdapted自身的adapt(),而上面CallAdapted类的adapt方法最终执行的是callAdapter.adapt(call),接下来就要分析下之前遗留的四个参数中的callAdapter了
2.2.2 CallAdapter
- CallAdapter是一个接口,主要用于创建
Call
对象,并指定如何处理异步请求和响应,例如自身默认的DefaultCallAdapterFactory和插件RxJavaCallAdapter都是它的实现
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call);
abstract class Factory {
/** 获取CallAdapter实例 */
public abstract @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
- 追一下刚刚CallAdapted类中的callAdapter,是在HttpServiceMethod.parseAnnotations()方法中获取并通过CallAdapted构造传入的
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
/**
* 检查接口方法上的注释,以构造一个可重复使用的HTTP服务方法。需要通过反射,所以需要使用缓存进行重用
*/
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
...
// 注释1
// 获取CallAdapter,分析可发现这里最后返回的是DefaultCallAdapterFactory
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
...
if (!isKotlinSuspendFunction) {
// 不是Kotlin协程的suspend方法
// 返回一个新建的CallAdapted对象,传入requestFactory, callFactory, responseConverter, callAdapter
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
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得知callAdapter是由createCallAdapter方法返回的
// HttpServiceMethod.java
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) {
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
- 最终从retrofit.callAdapter()获取
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(
@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
...
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;
}
}
...
}
- 最终是获取的callAdapterFactories中配置的callAdapterFactory,在2.2.1 Retrofit对象的创建中 得知,默认会添加DefaultCallAdapterFactory
final 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) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
// 注释1
// 判断请求方法上是否有@SkipCallbackExecutor注解,有返回null,没有返回callbackExecutor
// 注意默认情况下callbackExecutor在Java平台也是null,而在Android平台返回MainThreadExecutor
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
// 返回CallAdapter的匿名实现类 注释2
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
// 最终会调用这里 注释3
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()) {
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));
}
});
}
...
}
}
- 从上面得之CallAdapter是从DefaultCallAdapterFactory.get()返回的,从上面代码的注释1可得知返回的是一个匿名CallAdapter实现类,从2.2.1得知最后走的是CallAdapter.adapt()方法,所以这里最终会执行这个匿名CallAdapter实现类的重写方法adapt()
- 在adapt()方法里(注释3)中,会对executor进行判断,如果为null直接返回call,即上面分析的
OkHttpCall
,否则返回ExecutorCallbackCall
;至于这个excutor则是在注释1处进行判断的,通过判断请求方法中是否包含@SkipCallbackExecutor注解,如果有就返回null,没有就返回callbackExecutorcallbackExecutor默认情况下在Java平台返回null而Android平台会返回MainThreadExecutor
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
...
}
class Platform {
...
@Nullable
Executor defaultCallbackExecutor() {
return null;
}
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
// callbackExecutor是从这里传入的
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
...
static final class Android extends Platform {
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
...
}
- callbackExecutor是从PlatForm.defaultCallAdapterFactories()传入的,继续追这个方法的调用
public final class Retrofit {
...
public static final class Builder {
...
public Retrofit build() {
...
// 执行请求回调的对象,Android中defaultCallbackExecutor是MainThreadExecutor即主线程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 注释1
callbackExecutor = platform.defaultCallbackExecutor();
}
// 网络请求适配器工厂集合
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
...
}
}
}
- 由上面的注释1可得最终是获取得platform.defaultCallbackExecutor(),这就证明了上面得结论:默认情况下在Java平台返回null而Android平台会返回
MainThreadExecutor
,也就是Java平台最终会返回OkhttpCall,Android平台返回ExecutorCallbackCall
2.2.3 OkhttpCall & ExecutorCallbackCall
- 先看下这个OkhttpCall,它可以理解为okhttp3.Call的封装
/** 对okhttp3.Call的封装 */
final class OkHttpCall<T> implements Call<T> {
/** OkHttp的请求Request的封装 */
private final RequestFactory requestFactory;
private final Object[] args;
/** okhttp3.Call.Factory可以理解为okhttpClient */
private final okhttp3.Call.Factory callFactory;
private final Converter<ResponseBody, T> responseConverter;
private volatile boolean canceled;
/** 持有对okhttp3.Call的引用 */
@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;
@GuardedBy("this")
private @Nullable Throwable creationFailure;
/** 是否已经执行execute的标志位(是否已经在请求队列) */
@GuardedBy("this")
private boolean executed;
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;
}
...
/** 返回okhttp3.Call,有异常抛出 */
@GuardedBy("this")
private okhttp3.Call getRawCall() throws IOException {
okhttp3.Call call = rawCall;
if (call != null) return call;
...
try {
return rawCall = createRawCall();
} catch (RuntimeException | Error | IOException e) {
throwIfFatal(e);
creationFailure = e;
throw e;
}
}
/** 异步请求 */
@Override
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
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 {
// 构建okhttp.call 注释1
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
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
}
}
});
}
/** 同步请求 */
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = getRawCall();
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
/** 利用okhttpClient创建okhttp3.Call对象 */
private okhttp3.Call createRawCall() throws IOException {
// 注释2
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
/** 负责请求响应的解析 */
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
...
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
// 解析请求响应
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
...
}
}
- 回忆下Retrofit的请求步骤,从上文分析api.getBanner()返回的是一个OkhttpCall(Android平台是ExecutorCallbackCall,这个稍后分析),接下来的步骤就是通过异步调用okhttpCall.enqueue()或同步调用okhttpCall.execute(),我们直接看这两个方法
- enqueue()中先在注释1处通过
createRawCall()
拿到okhttp.call,具体的方法就一行 okhttp3.Call call = callFactory.newCall(requestFactory.create(args)),这个callFactory就是okHttpClient,这也符合okHttp创建Call的步骤,所以参数中requestFactory.create(args)必然返回的是okhttp.Request,这个后面分析RequestFactory
时再细讲 - 按照okhttp的请求步骤,接着就是接管okhttp中call.enqueue()的请求回调,在成功回调中对响应数据进行解析后用自己的回调去响应即可,失败就原样回调接管返回,而同步请求execute()就直接解析就可以了
- 接着看下ExecutorCallbackCall是个啥
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
/** Call代理,这里传入的其实就是okHttpCall */
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()) {
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));
}
});
}
@Override
public boolean isExecuted() {
return delegate.isExecuted();
}
@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
@Override
public void cancel() {
delegate.cancel();
}
@Override
public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone")
@Override
public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override
public Request request() {
return delegate.request();
}
@Override
public Timeout timeout() {
return delegate.timeout();
}
}
- 其实就是用到了装饰器模式和静态代理,在不改变OkhttpCall的情况下,其他方法均由okhttpCall这个代理对象进行操作,只对enqueue()方法使用callbackExecutor进行装饰,之前分析得到在Android平台callbackExecutor是一个MainThreadExecutor对象
// Platform.java
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
- 其实就是在接口返回中使用Handler包装一层实现线程的切换(okhttp请求是单独开启线程的,回调也是发生在子线程的)这样更适合Android平台,方便请求后直接操作UI
2.2.4 RequestFactory
- 刚刚上面说到会使用requestFactory.create(args)构造一个okhttp.Request对象,现在就来看下里面的魔法
/**
* 请求封装,主要是将Retrofit的请求转换为OkHttp的请求
*/
final 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;
/** 请求是否是一个Kotlin协程中的挂载函数 */
final boolean isKotlinSuspendFunction;
...
}
- 第一个方法就是parseAnnotations()方法,就是在ServiceMethod.parseAnnotations()中调用的,主要还是用到了Builder模式来构建RequestFactory对象
- RequestFactory中还包含一些请求相关的成员变量,例如请求地址、请求方法、请求头等,这里有一个isKotlinSuspendFunction变量主要是判断请求方法是否是一个Kotlin中的挂载函数,具体后面分析Kotlin协程返回再具体分析
- 直接看requestFactory.create(args)看下它是如何构造出一个okhttp.Request对象的
/**
* 创建okhttp3.Request对象
* @param args
* @return
* @throws IOException
*/
okhttp3.Request create(Object[] args) throws IOException {
@SuppressWarnings("unchecked") 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) {
// kotlin挂载函数(suspend关键字)编译成class会比java多一个Continuation类型的参数,所以此处需要-1
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();
}
- 主要是构造了一个RequestBuilder对象,并调用改对象的get()方法返回一个okHttp的Request.Builder对象,最后使用这个对象调用build()方法就可以构造出okhttp.Request对象了,我们看下这个RequestBuilder对象
final class RequestBuilder {
private final String method;
private final HttpUrl baseUrl;
private @Nullable String relativeUrl;
private @Nullable HttpUrl.Builder urlBuilder;
private final Request.Builder requestBuilder;
private final Headers.Builder headersBuilder;
private @Nullable MediaType contentType;
private final boolean hasBody;
private @Nullable MultipartBody.Builder multipartBuilder;
private @Nullable FormBody.Builder formBuilder;
private @Nullable RequestBody body;
...
Request.Builder get() {
HttpUrl url;
HttpUrl.Builder urlBuilder = this.urlBuilder;
if (urlBuilder != null) {
url = urlBuilder.build();
} else {
url = baseUrl.resolve(relativeUrl);
if (url == null) {
throw new IllegalArgumentException(
"Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
}
}
RequestBody body = this.body;
if (body == null) {
// Try to pull from one of the builders.
if (formBuilder != null) {
body = formBuilder.build();
} else if (multipartBuilder != null) {
body = multipartBuilder.build();
} else if (hasBody) {
// Body is absent, make an empty body.
body = RequestBody.create(null, new byte[0]);
}
}
MediaType contentType = this.contentType;
if (contentType != null) {
if (body != null) {
body = new ContentTypeOverridingRequestBody(body, contentType);
} else {
headersBuilder.add("Content-Type", contentType.toString());
}
}
// 这里构建OkHttp.Request.Builder对象
return requestBuilder.url(url).headers(headersBuilder.build()).method(method, body);
}
- 主要是挟持了okhttp的诸多对象,通过对请求方法中的注解的解析,最后包装成一个OkHttp.Request对象
2.2.5 Retrofit如何支持协程
- 首先看下它是如何判断请求方法是一个Kotlin挂载(suspend)函数,我们先看下kotlin的suspend函数转变成Java的样子,找到刚刚的Api.kt编译后的class(build目录中),使用Android Studio自带的Kotlin工具Decompile to Java会编译成
public interface Api {
@GET("banner/json")
@Nullable
Object getBanner(@NotNull Continuation var1);
@GET("banner/json")
@Nullable
Object getBanner2(@NotNull Continuation var1);
@GET("banner/json")
@NotNull
Call getBanner3();
}
- 可见suspend方法比普通的Java方法多出一个Continuation参数(最后一个参数),看下Retrofit中是不是从这点来判断的
final class RequestFactory {
...
/** 请求是否是一个Kotlin协程中的挂载函数 */
final boolean isKotlinSuspendFunction;
```
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;
}
}
// 判断请求方法的最后一个参数是否是Continuation类型,是就是一个suspend函数
if (result == null) {
if (allowContinuation) {
try {
if (Utils.getRawType(parameterType) == Continuation.class) {
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
...
}
- 的确源码就是根据这个参数来判断的,看下parseAnnotations()中协程相关部分
// HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
/** 是否是协程调用 */
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
/** 协程返回是否是Response包装实体 */
boolean continuationWantsResponse = false;
/** 协程返回是否是null */
boolean continuationBodyNullable = false;
...
if (!isKotlinSuspendFunction) {
// 不是Kotlin协程的suspend方法
// 返回一个新建的CallAdapted对象,传入requestFactory, callFactory, responseConverter, callAdapter
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
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);
}
}
- 这里的
isKotlinSuspendFunction
就是从requestFactory获取的,当为协程时,判断请求返回类型是Response还是T,这里就以T为例,最终返回的是一个SuspendForBody对象
static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
private final boolean isNullable;
SuspendForBody(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, Call<ResponseT>> callAdapter,
boolean isNullable) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
this.isNullable = isNullable;
}
@Override
protected Object adapt(Call<ResponseT> call, Object[] args) {
call = callAdapter.adapt(call);
Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
try {
return isNullable
? KotlinExtensions.awaitNullable(call, continuation)
: KotlinExtensions.await(call, continuation);
} catch (Exception e) {
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
}
- 按照上一篇的分析,最终会执行adapt方法,这个isNullable是从上面parseAnnotations()方法中的continuationBodyNullable传递的,为false,所以最终会执行
KotlinExtensions.await(call, continuation)
/** Call的扩展函数 */
suspend fun <T : Any> Call<T>.await(): T {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful) {
val body = response.body()
if (body == null) {
val invocation = call.request().tag(Invocation::class.java)!!
val method = invocation.method()
val e = KotlinNullPointerException("Response from " +
method.declaringClass.name +
'.' +
method.name +
" was null but response body type was declared as non-null")
// 协程返回请求错误
continuation.resumeWithException(e)
} else {
// 协程返回
continuation.resume(body)
}
} else {
continuation.resumeWithException(HttpException(response))
}
}
override fun onFailure(call: Call<T>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
-
就是利用kotlin的高阶函数给Call添加一个await扩展函数,再在onResponse回调中,通过协程挂起来执行耗时任务,而成功与失败会分别通过
resume()
与resumeWithExecption()
来唤起挂起的协程,让它返回之前的挂起点,进行执行
2.3 流程图和类图
-
大致流程图
-
类图
2.4 Retrofit使用的设计模式
2.4.1 Builder模式
- 关于Builder模式,可以看下设计模式~Builder模式
- Retrofit中使用Builder模式的地方,大概有
Retrofit对象的构建
、RequestFactory对象的构建
2.4.2 代理模式
- Retrofit中的核心就是使用到了代理模式,包含通过动态代理将每一个请求方法构建成OkHttpCall
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
// 如果方法是Object类中的方法,直接正常调用即可,无需代理
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
// 这里判断了是否是默认方法(java8接口新增了默认方法),不是就调用loadServiceMethod
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
- Retrofit中也使用了静态代理,ExecutorCallbackCall中,使用delegate(OkHttpCall)静态代理执行了Call的一些抽象方法,而无需自行实现
// DefaultCallAdapterFactory.java
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
/** Call代理,这里传入的其实就是okHttpCall */
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));
}
});
}
@Override
public boolean isExecuted() {
return delegate.isExecuted();
}
@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
@Override
public void cancel() {
delegate.cancel();
}
@Override
public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override
public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override
public Request request() {
return delegate.request();
}
@Override
public Timeout timeout() {
return delegate.timeout();
}
}
2.4.3 装饰模式
- 设计模式~装饰模式 - 掘金 (juejin.cn)
- 上面的ExecutorCallbackCall其实也是一个装饰模式,对Call的其他实现类进行装饰,这里真正去执行请求的是OkHttpCall。之所以要有个装饰类,是希望做一些额外操作。这里的操作就是线程转换,将子线程切换到主线程上去,没有直接继承OkHttpCall是这样能降低ExecutorCallbackCall与OkHttpCall的耦合度
2.4.4 策略模式
- 策略模式定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。
- 在CallAdapter中可以添加多个CallAdapte.Factory对象,相当于我们封装了多个不同的适配算法CallAdapter.adapt();如系统默认的DefaultCallAdapterFactory和插件RxJava2CallAdapterFactory等
- 在Converter中可以添加多个Converter.Factory对象,相当于我们封装了多个不同的请求响应解析算法Converter.convert();如系统默认的BuiltInConverters和插件GsonConverterFactory等
2.4.5 外观模式
- 我们在
HTTP API
接口中定义了很多方法,参数都在方法上进行定义,只会告诉调用者需要传入哪些参数,具体的操作并不向外暴露,这个就是外观模式
interface Api {
/** 获取首页banner数据(普通方式返回Call包装的实体) */
@GET("banner/json")
fun getBanner(): Call<ApiResponse<List<Banner>>>
}
val api = retrofit.create(Api::class.java)
val call:Call<ApiResponse<List<Banner>>> = api.getBanner()
2.4.6 适配器模式
- Retrofit中,CallAdapter就采用了适配器模式为创建访问Call接口提供服务。默认情况下使用默认的 ExecutorCallAdapterFactory 将okhttp3.call转变成为 retroift中的call,如果设定RxJava,则将okhttp3.call转化为 Observable
转载自:https://juejin.cn/post/7258321382156976184