前言
本篇是orzangleli的投稿,源码分析经常会涉及到大段的源码,在我的建议下,作者尽量删掉了源码,而是通过自己的理解写了出来,辛苦作者~修改了好几次,希望大家都能通过自己的理解,将人家的源码,转化为自己的知识
PS:最近比较忙,公众号好久没更新了,后面会给大家一起补上~~
源码的分析将从基本的使用方法入手,分析retrofit的实现方案,以及其中涉及到的一些有趣的技巧。并且建议大家也去github下载一份源码,跟着本文理一遍基本的流程。
调用API方法,生成Call
其中主要涉及的方法如下图所示:
retrofit实例的创建,典型的builder模式,在它的Builder
方法里有两个地方需要关注下,一个是Platform.get()
方法。它通过Class.forName
获取类名的方式,来判断当前的环境是否在Android中,这在之后获取默认的CallAdapterFactory
时候将会用到,对这个方法感兴趣的可以跟过去查看下,这里就不贴了。另一个是在build()
中创建了OkHttpClient
。
好玩的地方开始了,因为篇幅限制仅保留核心代码。
可以看出创建API使用了动态代理,根据接口动态生成的代理类,将接口的都转发给了负责连接代理类和委托类的InvocationHandler
实例,接口方法也都通过其invoke
方法来处理。
在invoke
方法中,首先会通过Platform.get()
方法判断出当前代码的执行环境,之后会先把Object
和Java8的默认方法进行一个处理,也是在进行后续处理之前进行降噪。其中的关键代码其实就是最后三句,这也是这篇文章将要分析的。
创建之前,首先会尝试根据方法从一个缓存列表中取出ServiceMethod
实例,如果没有,在锁保护之后,还有再尝试一次,还是没有的情况下,才会去创建ServiceMethod
。ServiceMethod的创建于Retrofit类似,都是builder
模式。ServiceMethod创建的实际流程都放在了最后的build()
方法中,也就是上图里面的serviceMethod分之。
可以看到在build方法中,对CallAdapter
与Converter
进行了创建,这里跟踪之后将会回到retrofit
类中,在其中将会获取对应列表中的第一个可使用的对象,之后将会对API的方法和参数注解进行解析。
CallAdapter
和Converter
的创建比较简单,都是遍历retrofit中builder时设置的属性,获取第一个可使用的值作为结果。
在解析注解时,先通过instanceof
判断出注解的类型,之后进行解析注解参数值,并设置请求的方法、相对路径等属性。
方法参数注解的解析,也是通过instanceof
判断出注解的类型,之后将根据参数类型分成Collection、array、other三种情况处理参数,之后根据这些参数,调用ParameterHandler中的对应参数注解的静态类,创建出一个ParameterHandler实例。这样循环直到解析了所有的参数注解,组合成为全局变量parameterHandlers,之后构建请求时会用到。
ServiceMethod
创建完成之后,我们来看看下一行代码中的OkHttpCall
类,里面的包含了请求的执行和响应处理,我们来看看异步请求的做法。
在构造函数中传入了之前新建的serviceMethod
和动态代理invoke
方法传递来的args
参数。我们来看看其异步方法enqueue
,这里要注意下enqueue
传入的参数callback
,这个参数可能和很多人心中想的并不一样,它并不是用户在使用时传入的那个Callback
对象,是经过了CallAdapter
包装了一层之后的Callback
。
可以看到锁保护之后,调用createRawCall()
方法创建一个OkHttp3.Call实例,跟进来可以看到,做了两件事情,第一件事情,调用serviceMethod.toRequest
方法,创造出一个Request
对象,这个Request
对象就是根据之前提到的方法参数注解的集合parameterHandlers
创建的。第二件事是创建一个okhttp3.Call
对象,我们都知道Okhttp中创建这个对象的方法就是newCall,这和上面的代码如出一辙,那么callFactory
参数是不是就是OkHttpClient
呢?bingo!确实如此,稍微跟踪一下就可以发现,它的创建出现在Retrofit.Builder.build()
方法中,而参数就使用刚刚创建的request
对象,构成okhttp3.Call
,并返回。
Converter的引入是通过parseResponse(rawResponse)
方法完成的,在其中将对响应状态码做一些简单的判断处理,之后调用Converter的实现类对响应进行解析,再传递回用户的回调当中。
OK,分析完了。Retrofit的代码虽然相对是比较少,也比较容易理解的,不过却是很好的架构实例。其主要方法都在图中的三个类中,Retrofit配置converter、calladapter、创建okhttpclient;ServiceMethod创建converter、calladapter、解析注解;OkHttpCall执行请求,引入之前创建的converter、calladapter,最后将响应结果传入用户的回调中。