retrofit的精华就在于使用注解将网络请求抽象成接口以供使用,本文就来分析它是如何实现的。
public interface retrofitService {
@GET("try")
public Call getCall();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("baseurl")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
retrofitService retrofitService = retrofit.create(retrofitService.class);
retrofit.create(retrofitService.class):
public <T> T create(final Class<T> service) {
1 Utils.validateServiceInterface(service);
2 if (validateEagerly) {
eagerlyValidateMethods(service);
}
3 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.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
4 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
5 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
6 return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
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;
}
- 1.判断接口是否符合条件
Utils.validateServiceInterface
:
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
2.
validateEagerly
这个标记位在retrofit源码解析--基本使用和关键成员变量介绍中有介绍,它的作用是来判断是否立即解析接口中的方法,如今就看看它具体是怎么做的:
eagerlyValidateMethods
:
获取到平台(Platform)
,然后遍历接口中的方法,调用loadServiceMethod
。
loadServiceMethod
:
在loadServiceMethod中通过serviceMethodCache
来存储转换为ServiceMethod类型的Method
。
serviceMethodCache
这个变量在retrofit源码解析--基本使用和关键成员变量介绍中也有介绍,它的作用是存储接口中的方法,这里就是它的运用。3.通过动态代理将接口转换成适配器指定的类型。其中4、5、6这几行代码是
整个retrofit的重点,将进行重点解析
- loadServiceMethod()在标记2中已经介绍过,这里主要介绍
ServiceMethod
:
- loadServiceMethod()在标记2中已经介绍过,这里主要介绍
result = new ServiceMethod.Builder<>(this, method).build();
这里又是通过建造者模式来创建了ServiceMethod
,在retrofit源码解析--ServiceMethod
有具体分析
- OkHttpCall就是原生okhttp的Call,通过之前对okhttp的学习,知道call是发起网络请求的关键
- 6.在retrofit源码解析--ServiceMethod有具体分析