Retrofit源码解读(一)
文章会用注释的方式来进行解读,同时也是作者(菜鸡)看源码的心路历程
源码基于 retrofit2.6.0
retrofit的建立都是从这里开始
LoginService loginService = retrofit.create(LoginService.class);
那就点进create方法里面看一下
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.单接口代理的创建方式被参数安全所保障
public <T> T create(final Class<T> service) {
//检查接口里的方法是否规范以及接口是否继承了其他的接口
Utils.validateServiceInterface(service);
//validateEagerly == true 提前进行一些预处理操作
//这些其实看方法名就能看出来,先不深究,先把一套完整的流程弄清楚
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//返回了一个泛型 T 看命名应该是动态代理 传递了三个参数
//param1:传进来的接口的类加载器,
//param2:一个class数组 但是retrofit就只穿了你所创建的接口
/*
param3:一个InvocationHandler
是一个接口 跳转过去会有一段注释告诉你:
这个类是invocation handler的一个代理实例的实现。
每一个代理实例都与invocation handler有联系。当一个方法被代理实例调用时,
该方法调用的操作会被编码且分发到他自己的invocation handler的invoke方法中去(渣翻译,可能出错)
大概就是 把你传进去的接口的方法 都放到一个类里边去实现?这个意思吗?
不管怎么说 这个类里的invode()方法肯定是关键
为什么写这么啰嗦,问就是还没了解过动态代理,只是听说过
todo : 我好菜啊,过完这个就去吧动态代理给弄清楚了。。。
*/
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { 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.
//如果方法来自Object就延迟(?)到一个普通的调用?这两个if应该都是一些检查
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);
}
});
}
loadServiceMethod()方法
//现在出现了一个之前没有出现过的类ServiceMethod,待会儿再看,先看看这个方法干了什么
ServiceMethod<?> loadServiceMethod(Method method) {
//serviceMethodCache是一个ConcurrentHashMap 看名字就知道这是个缓存。。
ServiceMethod<?> result = serviceMethodCache.get(method);
//有缓存,直接返回缓存中的ServiceMethod
if (result != null) return result;
//出现了,同步锁,锁住了serviceMethodCache这个对象
//todo : synchronized 也不是特别清楚,整明白他!
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
//再做一次检查,看是不是已经实例化过了
if (result == null) {
//还是没有,自己创建。
//看方法,解析注释,猜测应该就是解析定义接口时,在接口方法上所添加的@GET @POST 之类的注释了
//传递的两个参数,一个是当前retrofit对象,还有就是传入的method
result = ServiceMethod.parseAnnotations(this, method);
//然后放入缓存。。
serviceMethodCache.put(method, result);
}
}
return result;
}
retrofit2.ServiceMethod类
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//RequestFactory内做了一些注释解析的操作 是一个把retrofit参数转为okhttp3参数的工具类
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
//然后调用别的类的方法又进行了一次注释解析??迷惑行为,去看看这个方法把
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
HttpServiceMethod.parseAnnotations()方法
//首先,这是一个HttpServiceMethod的构造方法
//这里我删去了一些对kotlin进行兼容的if判断
//这里官方有一个注释,意思是建立一个service method会因为反射有很大的开销,所以最好复用这个service method
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
Annotation[] annotations = method.getAnnotations();
Type adapterType;
//callAdapter 斯,这个addCallAdapterFactory(RxJava2CallAdapterFactory.create())
//emmm 开始了,终于有认识的了
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
//这个函数是不是也有点眼熟,addConverterFactory(GsonConverterFactory.create())
//emmm 有点意思了。
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
//retrofit.callFactory 返回Retrofit类里边就能轻易发现 这是一个OkHttpClient
okhttp3.Call.Factory callFactory = retrofit.callFactory;
//这里我删了一些对kotlin协程/挂起 的兼容、判断
//但问题不大,看看CallAdapted这个类干了什么吧
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
HttpServiceMethod.CallAdapted类
/**
* 这个类主要是完成一个构造方法类似的工作,初始化一些初值。完成参数传递。构建了一个HttpServiceMethod类
* 直接看下HttpServiceMethod类干了什么吧
*/
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
HttpServiceMethod<ResponseT, ReturnT> 类
这个类的代码太多了,就不完整的贴上来了。首先官方对这个类的注释是
- Adapts an invocation of an interface method into an HTTP call
- 翻译:把一个接口方法的调用转换进一个Http Call
同时它还是刚刚ServiceMethod
的一个子类,也就是说他实现了ServiceMethod
的invoke方法
不出意外的话,invoke方法的具体实现就在这儿了
这个是不是和之前提到的动态代理感觉扯得上关系了?
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
emmmm OkHttpCall出现了!!
仔细点进去一看。。。。。这个并不是真的OkhttpCall 这个类依旧在retrofit2的包名下
迷惑行为,差点被骗了。
但是再仔细看看
噢噢噢噢哦哦哦哦哦哦哦哦哦哦哦哦哦哦哦!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
retrofit2.OkHttpCall类
同样代码太长,就不贴出来了。
这个类实现了retrofit2.Call这个接口,同时也就是这个类完成了retrofit对okhttp的操作
在类中会有一个okhttp3.Call rawCall; 来进行对okhttp的操作;
举个栗子(仅保留关键代码)
@Override public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
好了,到这里就大概对retrofit有了一个了解了
总结
- retrofit的核心就是大家都知道的动态代理,其实就是那个
Proxy.newProxyInstance
的三个参数
1.ClassLoader 类加载器
2.Class<?>[] 这里传入若干接口,newProxyInstance会宣称实现所有传进去的接口,这样你就可以调用这些接口里的方法
3.InvocationHandler 每一个方法都会对应一个自己的InvocationHandler,通过它的invoke()逻辑来实现接口中的方法
- 对应到retrofit中
第二个参数Class<?>[] 中会传入你定义的接口
传入的接口中的方法最终会由HTTPServiceMethod中的invoke()方法来进行实现。也就是创建一个retrofit2.OkHttpCall<>()