retrofit2
yunshuipiao opened this issue · 0 comments
yunshuipiao commented
Retrofit
A type-safe HTTP client for Android and Java
基于 version 2.5.0 进行分析。
Demo
Retrofit 将 Http API 转换为 java 接口,因此可以做如下定义
public interface GitHubService {
// 请求方法和地址
@GET("users/{user}/repos")
// 参数和返回值定义
Call<List<Repo>> listRepos(@Path("user") String user);
}
生成 上述接口的实现类。
// 实例化 retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
// 创建接口实现
GitHubService service = retrofit.create(GitHubService.class);
发起异步请求,之后交给 okhttp 来做底层处理,回到之前对 okhttp 请求过程的分析。
Call<List<Repo>> repos = service.listRepos("octocat");
下面就针对每一部分进行源码分析。
Retrofit
首先对 retrofit 实例的创建,用的是建造者模式。这里直接看最后的 build() 过程,直接了解配置了什么参数。
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// okhttp call 创建工厂,工厂模式的体现。
// 将类实例化操作和使用对像的操作分开
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
// okhttp 对象,用于创建 call
callFactory = new OkHttpClient();
}
// 异步执行时进行回调
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
// call 调用适配器,使得返回接口定义的返回值
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
// 序列和反序列化转换器
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
// 所有的转换器
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
interface
接着就可以实现之前声明的接口。
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
// 最重要的部分
public <T> T create(final Class<T> service) {
// 判断是接口并且不能继承其他接口
Utils.validateServiceInterface(service);
if (validateEagerly) {
// 提前对 service 中的方法注解进行合法性验证
eagerlyValidateMethods(service);
}
// 使用动态代理生成对应的 Service
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
// 处理被代理对象的某个方法发生是调用,比如这里的 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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
// 加载 Service 并返回正在使用的方法
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;
}
在上面的过程中,代理类解析方法的相关注解,包括 http 的请求方法, 地址,参数等信息,内容比较多,可以深入去看。下面就到了请求过程。
上次还提到动态代理, 当 service.listRepos("octocat") 时,接口中的调用会集中转发到 InvocationHandler 的 invoke() 方法,集中进行处理。
请求过程
当发生方法调用时,请求过程会来到如下代码:
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
用相关的信息创建一个 okhttp 的 call 对象,
追下去就是 okhttp 的请求过程了。