Retrofit源码解读.

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/heming9174/article/details/88343500

近期准备面试,准备再复习一下基础,掏出Retrofit再过一遍.
做个记录,防止下次忘记了…

Retrofit 源码解读.

Retrofit 是什么?

没啥好说的


最好需要了解的额外知识

  1. 动态代理

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)

点进去,看到的是这样的:
create

这些代码就是整个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,回武汉.加油!

猜你喜欢

转载自blog.csdn.net/heming9174/article/details/88343500