- 关于动态代理,写在前面
分两点动态指的是在运行期,而代理指的是实现了某个接口的具体类,称之为代理,会调用了 InvocationHandler 的 invoke方法。
Retrofit 中的动态代理:
在代码运行中,会动态创建 GitHubApiService 接口的实现类,作为代理对象,代理接口的方法
在我们调用GitHubApiService 接口的实现类的 listRepos方法时,会调用了 InvocationHandler 的 invoke方法。
本质上是在运行期,生成了 GitHubApiService 接口的实现类,调用了 InvocationHandler 的 invoke方法。
- Retrofit.Builder()
public static final class Builder {
//储存默认的calladapter和converter,执行的build()的时候和add方法添加的一起传入建立的retrofit实例
private final Platform platform;
//根据request生成okhttp3.newCall
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
//储存add方法中加入的converter和calladapter
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
- retrofit.create(service)
通过动态代理创建service的实例
public <T> T create(final Class<T> service) {
//先检查传入的参数是否满足要求,然后遍历注解,只执行了loadServiceMethod()方法,将其储存在serviceMethodCache中,并没有invoke()。
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
其中 loadServiceMethod()
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;
}
- 解析注解
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//此方法可以实现method的复用,下次可以直接用不用解析注解,见源码的解析
//Inspects the annotations on an interface method to construct
//a reusable service method. This requires potentially-expensive
//reflection so it is best to build each service method only once
//and reuse it. Builders cannot be reused.
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.");
}
//此方法实现对注解进一步解析成http method,同时因为方法用了消耗大的反射,因此实现了复用,下次请求方法可以直接使用
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
- CallAdapter详细介绍
定义:网络请求执行器(Call)的适配器
Call在Retrofit里默认是OkHttpCall
在Retrofit中提供了四种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory
作用:将默认的网络请求执行器(OkHttpCall)转换成适合被不同平台来调用的网络请求执行器形式
如:一开始Retrofit只打算利用OkHttpCall通过ExecutorCallbackCall切换线程;但后来发现使用Rxjava更加方便(不需要Handler来切换线程)。想要实现Rxjava的情况,那就得使用RxJavaCallAdapterFactoryCallAdapter将OkHttpCall转换成Rxjava(Scheduler):
// 把response封装成rxjava的Observeble,然后进行流式操作
Retrofit.Builder.addCallAdapterFactory(newRxJavaCallAdapterFactory().create());
// 关于RxJava的使用这里不作更多的展开
Retrofit还支持java8、Guava平台。
好处:用最小代价兼容更多平台,即能适配更多的使用场景
ConverterFactory
网络请求,调用了okhttp3
// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();
- 关于协程
因为在代码编译的过程中会自动为带有suspend的函数添加一个Continuation类型的参数,并将其添加到最后面。所以上面的协程真正的面目是这样的:
@GET("/v2/news")
fun newsGet(@QueryMap params: Map<String, String>, c: Continuation<NewsResponse>): NewsResponse
所以在提取参数的注解的时候会专门将最后一个参数标注出来。将解析参数注解方法的allowContinuation参数设置为true,当result为Null即没有注解时如果时最后一个参数则判断是否是协程的参数类型
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
//1.解析方法参数的注解,并验证它们的合法性
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;
}
}
//2.判断是否是协程
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;
}
请求返回时
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
// 1. 是协程
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType = Utils.getParameterLowerBound(0,
(ParameterizedType) parameterTypes[parameterTypes.length - 1]);
// 2. 判断接口方法返回的类型是否是Response
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// Unwrap the actual body type from Response<T>.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
// 3. 注意:将方法返回类型伪装成Call类型,并将SkipCallbackExecutor注解添加到annotations中,跳过创建Executor,协程不需要Executor来切换线程
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
// 4. 创建CallAdapter,适配call,将其转化成需要的类型
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
// 5. 创建Converter,将响应的数据转化成对应的model类型
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
// 6. 接口方法不是协程
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
// 7. 接口方法是协程,同时返回类型是Response类型
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
// 8. 接口方法是协程,同时返回类型是body,即自定义的model类型
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
将Call转化成对应的Model
public SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
.....
@Override protected Object adapt(Call<ResponseT> call, Object[] args) {
// 1. 获取适配的Call
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
// 2. 获取协程的Continuation
Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
return isNullable
? KotlinExtensions.awaitNullable(call, continuation)
: KotlinExtensions.await(call, continuation);
}
}
对于伪装成call是在retrofit默认的callAdapter的开始有一个判断,如果是协程会被识别出来并跳过
//此为retrofit默认的callAdapter方法,即SuspendForBod.adpat()开始调用的方法
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
...
}
同时在协程自己的SuspendForBody()系列方法中实现了自己的adapt()方法,实现返回类型的转换
suspend fun <T : Any> Call<T>.await(): T {
...
// 1. 拿到body
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")
// 2. body为空,唤起协程,抛出异常
continuation.resumeWithException(e)
} else {
// 3. 唤起协程,返回body
continuation.resume(body)
}
}