众所周知,在现在的Android开发中,针对与网络请求,Retrofit+okHtt的组合绝对是不二之选,而在网上针对与Retrofit分析的文章也有很多了,这次我也分享一些阅读Retrofit源码的心得,希望能够对大家有所帮助。由于我在工作中使用的版本为2.1,所以本次也是针对2.1版本进行分析,首先来看看Retrofit一种简单的用法:
Retrofit简单使用示例
首先创建出Retrofit对象,进行相应的初始化配置:
1 | retrofit=new Retrofit.Builder() |
然后在Service接口中写入相应方法,并加上相应的注解:
1 | public interface Api { |
最后传入请求的回调方法Callback就可以就完成了:
1 | retrofit.create(Api.class).methodName().enqueue(Callback); |
对于Retrofit对象的Build中,主要的都是对于参数的初始化,所以本次就从Retrofit类中的create(final Class
Retrofit.create
1 | public <T> T create(final Class<T> service) { |
在这段代码的最后所返回的Call对象就是用来使用的Call对象了。
其中有一个很有趣的地方,在 Platform 类中有一个通过判断特定的类是否存在的方式获取当前平台的步骤,在我的2.1版本中有这么一段代码:
1 | try { |
但在最新的2.3版本中这段代码已被移除,这说明Retrofit在之前版本中有对IOS平台的支持,但是我在网上却没有找到相关的资料,不知道有没有哪位朋友能为我解答一下。
在上面的代码中,重点是最后的三行代码,下面就分别对于这三行代码进分析:
1.ServiceMethod serviceMethod = loadServiceMethod(method);
Retrofit.loadServiceMethod
下面来通过loadServiceMethod方法看看ServiceMethod对象是如何创建出来的
1 | ServiceMethod loadServiceMethod(Method method) { |
在代码中可以看出创建ServiceMethod对象主要都在ServiceMethod.Builder之中
在其中我发现了一点,在我所使用的2.1版本中,作为缓存使用的serviceMethodCache为LinkedHashMap,但在最新的2.3版本中已被换成了线程安全的ConcurrentHashMap。
ServiceMethod.Builder.Builder
首先看看Build中的构造方法:
1 | public Builder(Retrofit retrofit, Method method) { |
可以看出,构造方法中的代码很简单,就是针对各个变量的赋值操作。下面就是ServiceMethod中的重头戏,也就是build方法,对于注解的解析也都是在这里完成的,这一部分的代码虽多,但是大部分都是对于注解的解析与异常的判断,还是一样先来看看代码:
ServiceMethod.Builder.build
1 | public ServiceMethod build() { |
其中最重要的应该是属于对于方法与参数的注解解析的部分了,这也是Retrofit的特色之一,先来看看对于方法部分的注解解析:
ServiceMethod.parseMethodAnnotation
1 | private void parseMethodAnnotation(Annotation annotation) { |
可以看出来,这个方法中的逻辑很简单,主要是判断出注解的类型,并将对应的字符串传入之后的处理中,真正的处理还是在parseHttpMethodAndPath与parseHeaders两个方法中
ServiceMethod.parseHttpMethodAndPath
1 | private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { |
在除去其中异常判断后,这个方法的逻辑就变得非常清晰了
ServiceMethod.parsePathParameters
1 | static Set<String> parsePathParameters(String path) { |
这个方法也很好理解,使用正则表达式匹配出相对路径中以”{}”包裹的变量,然后放入Set集合中
ServiceMethod.parseHeaders
该方法的作用为Header注解的解析:
1 | private Headers parseHeaders(String[] headers) { |
ServiceMethod.parseParameterAnnotation
这个方法用于参数注解的解析
1 | private ParameterHandler<?> parseParameterAnnotation( |
parseParameterAnnotation这个方法中的代码虽然多,但是在简化之后可以看出来,就是针对不同的参数类型进行不同的处理然后返回相应的ParameterHandler对象,因为其中针对各个类型参数的处理比较繁琐,就不一一列举了。
需要提到的是,在这个方法中,有一个类的出现频率非常的高,这就是ParameterHandler类,这个类的主要作用是将注解中的各项参数通过RequestBuilder类转换为okHttp中使用的Request。
2.OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
在OkHttpCall类中,最主要的就是execute与enqueue两个方法,分别为同步与异步的网络请求,但是需要注意的是,这两个方法并不是我们在使用中所调用的方法,真正提供给外界调用的方法,会在文章之后的部分讲到。
OkHttpCall.execute
1 | public Response<T> execute() throws IOException { |
OkHttpCall.enqueue
1 | public void enqueue(final Callback<T> callback) { |
enqueue方法在主要的逻辑上,与上面的execute是基本相同的,但是有一点需要注意,就是当收到Response时并不会马上进行Callback中的onResponse回调,而是会调用parseResponse方法对返回的Response进行一次解析,如果解析中出现了异常,依然会进行onFailure的回调方法。
OkHttpCall.parseResponse
1 | Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { |
这个方法主要是对okhttp中返回的response进行一次解析,对其进行一些预处理,并将其转换为更易于使用的Response对象
OkHttpCall.createRawCall
1 | private okhttp3.Call createRawCall() throws IOException { |
这个方法主要用于创建okHttp中的Call对象,逻辑非常简单,就不多做分析了
3.serviceMethod.callAdapter.adapt(okHttpCall)
这个方法实际是使用在创建Retrofit对象时传入的CallAdapterFactory将OkHttpCall对象转换为最后使用所需的对象,Retrofit中会默认配置一个ExecutorCallAdapterFactory,除此之外还有常用的RxJavaCallAdapterFactory与一个最简单的DefaultCallAdapterFactory。我们抽取出其中的adapt方法来看一看:
DefaultCallAdapterFactory
1 | final class DefaultCallAdapterFactory extends CallAdapter.Factory { |
这个是Retrofit中最为基本的CallAdapter,也只有在平台为Java8或者无法判断平台时才会使用,也由于这个类的逻辑非常简单,也可以通过这个类了解到CallAdapter.Factory最核心的两个方法的作用
ExecutorCallAdapterFactory
ExecutorCallAdapterFactory类为Android平台的默认CallAdapter:
1 | final class ExecutorCallAdapterFactory extends CallAdapter.Factory { |
结语
那么,到现在为止,我们简单梳理了Retrofit中的Call的创建流程与ServiceMethod类中的主要逻辑,而这些,也只是Retrofi中的一部分而已,而我也是第一次写这样的文章,加上我的技术还不到位,所以肯定会有很多的不足,欢迎大家来批评指正。