kotlin 项目中最常用的网络请求模式就是 协程 + retrofit + okhttp
协程的挂起、调度可能需要较长的篇幅来介绍这里先分析下 retrofit 和 okhttp
Retrofit
请求的创建
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 动态生成传入 service 接口的代理类
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] {
service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// 如果是 object 方法直接调用即可,不需要经过 retrofit 封装
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 解析 service 注解
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
// 将 service method 封装到 okhttp 请求中
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
service 接口解析
loadServiceMethod:
ServiceMethod<?, ?> loadServiceMethod(Method method) {
// 先查看缓存中是否存在,熟悉的记忆化回溯写法,老 leetcoder 了
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
// 参数校验等操作,省略
...
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
// 解析 service 中的函数请求注解如 get 和 post 等
parseMethodAnnotation(annotation);
}
// 参数校验等操作,省略
...
// 解析传参的请求注解
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)