今天突然想到Retrofit2创建Service需要传递一个接口,但是我们都知道接口是不能直接生成实例的,那么Retrofit2是如何做到的呢?带着疑惑,看一波源码。
//创建实例
retrofit.create(VideoApis.class);
跟进create方法:
//此方法需要一个Class类
public <T> T create(final Class<T> service) {
//对传入的Class进行校验
Utils.validateServiceInterface(service);
if (this.validateEagerly) {
this.eagerlyValidateMethods(service);
}
return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
private final Platform platform = Platform.get();
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
} else if (this.platform.isDefaultMethod(method)) {
return this.platform.invokeDefaultMethod(method, service, proxy, args);
} else {
ServiceMethod serviceMethod = Retrofit.this.loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
}
});
}
一进入create就调用了一个验证方法 Utils.validateServiceInterface(service);看下源码做了什么事情:
static <T> void validateServiceInterface(Class<T> service) {
//首先验证此类是否是接口,不是接口直接抛出异常。
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
//继续判断此类是否是独立的接口类,如果有继承其他接口则抛出异常。
} else if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
返回源码继续分析校验通过过后的代码:
//这里直接return了,后面的实例是使用了动态代理获取了接口的实例。。。
return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
private final Platform platform = Platform.get();
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
} else if (this.platform.isDefaultMethod(method)) {
return this.platform.invokeDefaultMethod(method, service, proxy, args);
} else {
//前面可以忽略,这里会走此方法
ServiceMethod serviceMethod = Retrofit.this.loadServiceMethod(method);
//这里主要是利用源方法的信息,包装在ServiceMethod中,然后连带参数一并传递到OkHttpCall,构建出一个OkHttpCall的实例,通过代理类执行接口中定义的方法。
OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
}
});
此时我们已经知道Retrofit是通过动态代理,最终使用的okhttp的实例来执行接口中的方法,顺便追踪下ServiceMethod 的出处:
//serviceMethodCache 是定义的一个缓存Map
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap();
...
ServiceMethod loadServiceMethod(Method method) {
Map var3 = this.serviceMethodCache;
synchronized(this.serviceMethodCache) {
ServiceMethod result = (ServiceMethod)this.serviceMethodCache.get(method);
if (result == null) {
//主要看result的创建
result = (new retrofit2.ServiceMethod.Builder(this, method)).build();
this.serviceMethodCache.put(method, result);
}
return result;
}
}