Retrofit2-源码解析,kotlin协程android

本文详细分析了Retrofit2的源码,特别是`ServiceMethod`的创建过程,包括`loadServiceMethod`的DCL单例模式,以及`createCallAdapter`和`createResponseConverter`方法,揭示了Retrofit如何根据方法注解生成HTTP请求配置。同时,文章提及了Kotlin协程在Android环境中的应用,强调了Retrofit在构建`OkHttpCall`对象时的角色,以及如何通过`adapt`方法将请求适配到主线程执行。
摘要由CSDN通过智能技术生成

(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}

这里我们看到了 validateEagerly 变量,让我们看看它到底控制了什么。进 eagerlyValidateMethods 方法。

private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}

ServiceMethod<?, ?> loadServiceMethod(Method method) {
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;
}

这里又见到了 Platform ,在 Retrofit.Builder 我们知道它返回的是 Android() 对象。 接着是个 循环 ,循环取出接口中的 Method ,接着调用 loadServiceMethod 。 loadServiceMethod 里面会根据 Method 生成一个 ServiceMethod,然后存入 serviceMethodCache , 那么我们大概知道,这是属于提前验证,会提前把接口中每个方法进行解析得到一个 ServiceMethod 对象,然后存入缓存中。 在 loadServiceMethod 中会取缓存中的值,如果有就直接返回 ServiceMethod。

由此可以知道 validateEagerly 变量是用于 判断是否需要提前验证解析的。

create 方法中 继续往下走,会看到 return 一个 代理对象 Proxy ,并转成了 T 类型,即 GitHubService 。
此时我们这句代码 GitHubService service = retrofit.create(GitHubService.class); 中的 service 有值了,它指向一个 实现了 GitHubService 接口的 代理对象 Proxy 。

3. 拿到 Call 对象 , 即 Call<List<Repo>> repos = service.listRepos("octocat");

这里我们的 service 是个代理对象,所以执行 listRepos 方法时, 会先走 InvocationHandler 中的 invoke 方法。

public T create(final Class service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(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 {
// If the method is a method from Object then defer to normal invocation.
// 如果这个方法是声明在 Object 类中,那么不拦截,直接执行
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 这个总是返回的false,所以不用关心
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}

// 下面三行代码非常重要,重点分析,分别对应 3.1 3.2 3.3 三个小节
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}

3.1 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);

首先 ServiceMethod 我们之前猜测过,应该是对 Method 的一个封装, 而这个 loadServiceMethod ,如果你还记得的话,我们在 create 的时候就碰到过,eagerlyValidateMethods 这个方法内部调用过 loadServiceMethod ,是为了加载这个 ServiceMethod 。现在我们来深入分析这个 loadServiceMethod 方法。

ServiceMethod<?, ?> loadServiceMethod(Method method) {
// 首先从 缓存 serviceMethodCache 中取 ServiceMethod ,如果存在就返回,不存在继续往下走。
// 也就是说 我们的 ServiceMethod 只会创建一次。
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;

synchronized (serviceMethodCache) {
//这里又从缓存取了一遍,看到这里有没有一种熟悉的感觉,是不是跟 DCL 单例模式特别像,双重校验。
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值