近期准备面试,准备再复习一下基础,掏出Retrofit再过一遍.
做个记录,防止下次忘记了…
Retrofit 源码解读.
Retrofit 是什么?
没啥好说的
最好需要了解的额外知识
- 动态代理
https://blog.csdn.net/briblue/article/details/73928350
看一下大佬对于这个的讲解吧
TIPS
Retrofit 版本不同,对应的源码有差异,
本次解读使用的版本为:.2.5.0
Begin.
常见的Retrofit初始化和调用肯定是这样的:
mRFIDService = new Retrofit.Builder()
.baseUrl(Const.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())//可选
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//可选
.build()
.create(RFIDService.class);
mRFIDService.upLoad(requestMap).enqueue(new Callback<Response>() {
@Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
}
@Override
public void onFailure(Call<Response> call, Throwable t) {
}
});
首先需要关注的是如何将传入的一个Interface的类(TestService)转换成了一个Interface的对象(mTestService),然后调用这个对象的方法(upLoad).
create(Class service)
点进去,看到的是这样的:
这些代码就是整个Retrofit最关键的代码!
其中值得注意的几个点分别是:
1.Utils.validateServiceInterface(service)
它是用于判断 这个class是否为一个接口类型以及,这个接口是否是一个单一的接口,而不是继承了其他父类的接口.
2.提前全部校验.
提前完整校验各种请求参数的合法性,适用于开发调试阶段.产品发布生产阶段不推荐,否则可能导致额外的性能开销.
3.动态代理模式Proxy.newProxyInstance()
这就是别人口中常说的Retrofit的动态代理的部分
4.invoke方法内
method.getDeclaringClass() == Object.class
只要我的APIService里面的对应方法他是Object的方法(我自己单独写的方法,那么肯定不是Object类的方法),就默认不做任何处理.只处理我自己单独写的方法.
那么我们如何获取这个Interface对象呢?
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
ServiceMethod对象的获取–上半部分
1.如何获取loadServiceMethod
发现我们是通过serviceMethodCache来获取这个ServiceMethod的.这个serviceMethodCache是一个Map的缓存.
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
当已经存在时,直接通过method这个key直接获得对应的value.如果不存在,DCL后,通过
ServiceMethod.parseAnnotations(this, method);
来创建它
2.创建ServiceMethod.
主要有2个步骤,分别是红框标注的2个地方.
3. RequestFactory.parseAnnotations(retrofit, method)获得RequestFactory.
return new Builder(retrofit, method).build();
里面很简单,使用了Build设计模式.
4.new Build(retrofit,method)
分别保存了 retrofit对象,method对象,method的注解(如GET/POST/urlencode等),method的参数类型,method的参数的注解(如@path,@body,@parm等)
5. .build();
这里面首先是**parseMethodAnnotation()**通过获取到的method的注解,对HTTP请求的head部分进行了判断处理,获取到了headers.
然后进行各种判断,比如说POST请求,就必须拥有一个body,表单请求的Content-type也必须要拥有一个body等.
最后返回了一个RequestFactory,里面存着HTTP请求的各种参数.
以上可以称之为retrofit对于HTTP请求的前期处理.后期处理将交由这个类(ServiceMethod)的子类(HttpServiceMethod)来进行处理.
HttpServiceMethod的对象的创建
分别做解释.
1.创建CallAdapter.
发现它是通过
(CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
来创建的,点进去,发现它调用的是 nextCallAdapter()
.
2.nextCallAdapter()
我们需要的callAdapter是通过一个叫做callAdapterFactories里面获取到的.
而且要注意的是,我们肯定拥有一个默认的callAdapter,否则就直接抛异常了.
那么我们如果我们没有添加一个额外的,默认的哪里来的呢?
我们这里先暂停,返回到HttpServiceMethod继续往下看代码,看看后面的
3. 创建Converter
发现它是通过
retrofit.responseBodyConverter(responseType, annotations);
来创建的,点进去,发现它调用的是nextResponseBodyConverter
emmm…
这熟悉的感觉 !!!
4. nextResponseBodyConverter
完全是一毛一样啊,我就不当复读机了.
同上!
发现它也是通过一个叫做converterFactories里面获取到的.
ServiceMethod对象的获取 – 下半部分
1.callAdapterFactories和converterFactories
发现了木有,Retrofit的里面有2个方法,分别是addXXX()和addXXX().
然后就添加到callAdapterFactories和converterFactories集合里面去了.
可以将我这手动额外添加的设置进来.
如果没有添加呢,那默认值在哪里?
直接拉到Retrofit源码的最下面,发现在Retrofit的build()里面,有相关的默认值的赋予.
2. callbackExecutor
我们发现在创建一个系统默认的CallAdapter.Factory,传入了一个platform.defaultCallbackExecutor();
点进去.
发现在Platform的defaultCallbackExecutor内,直接返回的是Null,类里面搜索一下.
咋Platform内部类Android内我们发现了:
这不是handler使用的那个MainLooper么.
原来这个callbackExecutor的作用就是将它的参数Runable内的信息传递到主线程.
3.callAdapterFactories的默认值.
返回到创建CallAdapter.Factory,我们点开
platform.defaultCallAdapterFactories(callbackExecutor);
我们继续点,发现它最后获得是一个叫做ExecutorCallAdapterFactory的CallAdapter.Factory.
我们此时知道了
this.callbackExecutor = callbackExecutor;这个callbackExecutor的作用就是将内容传递到主线程.
4. converterFactories的默认值.
我们发现这个根据Android SDK的版本,会返回不同的结果,不过好在Retrofit已经给我们添加了一个BuiltInConverters.
5. 返回HttpServiceMethod.
当CallAdapter(手动添加或者使用系统默认),Converter(手动添加或者使用系统默认)都准备好了以后,正式给我们返回了HttpServiceMethod()对象.
invoke – 接口方法的调用.
我们通过ServiceMethod的前期准备获取到了HTTP请求的head,body,
通过了HttpServiceMethod获取到了请求对象接收对象(Call还是Call的子类还是Observable),自动转换器(手动添加GsonConverterFactory,自动将Response的body转成制定的类型).
那么 请求呢? HTTP请求是如何发出的呢? 对应的响应又是如何接收,如何处理的呢?
我们再次回到这里.
其中**loadServiceMethod(method)**我们已经创建成功了(或通过serviceMethodCache获取之前的缓存).
而且这个对应的是HTTPServiceMethod.我们打开对应的invoke().
1.callAdapter.adapt
其中callAdapter是什么我们已经知道了,就是ExecutorCallAdapterFactory.
找到对应的adapt.
注意里面传入的call,就是HTTPServiceMethod里面传入的new OkHttpCall<>()
OkHttpCall – enqueue/execute
当我们最后通过enqueue/execute调用时.
即调用了OkHttpCall的enqueue/execute.
我们以enqueue举例.
1.createRawCall()
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
createRawCall即通过okhttp来创建一个okhttp的Call
2. parseResponse(rawResponse);
call.enqueue正式请求网络,在onResponse对请求成功的结果进行解析.
解析响应码
小于200,大于等于300,算error.
等于204或205时,直接返回null的 body.
只有200才是正常返回.
3.OkHttpCall的请求回调
经过请求,并且对响应码进行处理后的response.
通过
callback.onResponse(OkHttpCall.this, response);
callback.onFailure(OkHttpCall.this, e);
回调给ExecutorCallbackCall的enqueue的onResponse里面的子线程run方法内.
4. MainThreadExecutor
还记得这个
callbackExecutor.execute(runnable r)这个callbackExecutor吗?这就是在创建默认CallAdapter.Factory里面传入的callbackExecutor,也就是MainThreadExecutor.
此时正好.
OkHttpCall在子线程去进行HTTP请求,将内容进行解析,回调到run方法内,callbackExecutor的execute方法则负责将内容传递至主线程,然后我们又创建了Callback,在Callback的OnResponse和onFailure内拿到已经切换到主线程的,已经被根据响应码处理过的response了.
总结.
其实Retrofit的整体脉络,层级还是很简单的.
只是细节上有点复杂.
整体的调用逻辑是这样的:
网络请求:
写在最后.
好久没写Blog了,感觉知识这个东西,自己了解掌握了是一种难度;把这份理解讲给被人听,是另外一种难度;最后将这份理解写出来,分享给大家,更是一种难度.
2019,回武汉.加油!