好的代码是自解释的,Retrofit 可以算是好的代码了。
一、无中生有:从接口方法到Request实例
ServiceMethod.java
将 API接口 中定义的方法方法转化为
HTTP
请求。接口中描述的方法是没有方法体的,所以最终执行的时候需要根据接口信息去组织特定的方法和对象,以产生可以执行的代码。
1 | ({ |
ServiceMethod
虽然没有继承自 java.lang.reflect.Method
,但是同样提供了执行方法的途径。由内部类 Builder
中的 parseMethodAnnotation(Annotation annotation)
/*参见 Retrofit源码分析:方法注解*/ , parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody)
, parseHeaders(String[] headers)
, parseParameter(...)
, parseParameterAnnotation(...)
等方法来转换成一个“有血有肉”的 OkHttp 请求。
一段很有意思的代码:
- @Path 注解表示的 URL 不能和参数化查询混淆(形如
/{name}/address?type=home
)#294 ~ #303
1 | int question = value.indexOf('?'); |
RequestBuilder.java
负责构建
Request
对象的具体实现。分离职责
ServiceMethod
中有个 “根据方法参数构建 HTTP 请求” 的方法,就是把从接口方法中解析到的数据传到这里来创建请求的。目前只有构建 Request 实例的过程中用到了这个类。主要有下面这些方法,这些方法都是
ParameterHandler
在用。使用 IntelliJ / Android Studio 快捷键
alt+f7
可以快速查找依赖 (要把 作用域Scope 设置为 Project and Libraries )
ParameterHandler.java
负责处理参数,是具体实现。分离职责
里面有一些内部类:
RelativeUrl
,Header
,Path
,Query
,QueryName
,QueryMap
,HeaderMap
,Field
,FieldMap
,Part
,RawPart
,PartMap
和Body
等内部类。这些内部类都继承自
ParameterHandler
, 并重写了apply()
(也是唯一一个可供重写的方法)。这些类的实例供ServiceMethod
使用。目前只有构建 Request 实例的过程中用到了这个类。
二、 天堑变通途,Request 和 Response
Call.java
每次调用 Retrofit 方法会向服务器发起请求并得到一个响应。
在 Retrofit 中,仅有一个实现类:
OkHttpCall
。Retrofit 通过动态代理使用的也有一个类,即所有的 Retrofit中的所有接口方法使用的都是OkHttpCall
。见 Retrofit 中的public <T> T create(final Class<T> service)
方法。接口共有七个方法,
Response<T> execute()
、void enqueue(Callback<T> callback)
分别同步、异步发出请求;void cancle()
用来取消请求;boolean isExecuted()
、boolean isCanceled()
用来获取当前请求的状态;Retrofit 中每个请求只能执行一次,当需要轮询或者失败重传的时候,可以使用Call.clone()
来产生同样的请求;Request request()
可以获取生成的Request
对象(并没有执行request
,而是一个getter
方法,retrofit
中好多(可能是所有)getter
方法都是这种风格的,方法名不以get
开头)。
OkHttpCall.java
Call
的唯一实现类
execute
和 enqueue
的代码片段(一个 Call 只能执行一次):
1 | if (executed) throw new IllegalStateException("Already executed."); |
execute
和 enqueue
函数的结构很相似,拿 enqueue
来说(移除了错误处理代码,并 inline
了部分函数):
1 | public void enqueue(final Callback<T> callback) { |
可以看到这个方法中进行了一次复制,使用原来的 call
并间接调用了 callback
。为什么要这样多此一举呢?这跟 Retrofit 请求道路的曲折性是分不开的。当 通过 OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args)
这个构造方法创建对象后,得到的 call 对象就是个简单的对象而已,无法完成网络请求,需要在内部通过callFactory
创建。
createRawCall
根据构造函数中传入的 args
, 创建新的 request
,并根据 request
创建 Call
(代码中出现的 callFactory
默认情况下是 Retrofit 创建的 ,真正的实例是 OkHttpClient
,这个类实现了 Call.Factory
接口 。OkHttpClient
中的实现是 return RealCall.newRealCall(this, request, false /* for web socket */)
。很明显,真正进行请求的是RealCall
,代码中的 rawCall
的类型一般情况就是 RealCall
啦!这也就说通了为什么会有这么一层包装,因为 OkHttpCall
就是个中间层!):
1 | private okhttp3.Call createRawCall() throws IOException { |
解析响应 response
, 所有的分支都是 return Response.success/error(...)
的形式, Response
类中 success
和 error
的几个静态重载方法会返回带有泛型的 Response
。
1 | Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { |
Callback.java
对于绝大多数 Android开发者来说,这个接口是相当熟悉的。
onResponse
&onFailure
分别对应请求成功和失败
Response.java
对
okhttp3.Response
的一个简单封装包含一些
getter
方法(delegate)和几个用来创建Response
的静态方法(success
和error
的重载方法)。
三、Factory、Adapter、Converter
Converter.java
此接口包含了一个方法:
T convert(F value)
和一个抽象内部类Factory
。Factory
产生特定的Converter
。
Factory
有三个可供重写的方法:
responseBodyConverter(Type type,Annotation[] annotations, Retrofit retrofit)
requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit)
返回处理 HTTP Request 的
Converter
,某种类型(在接口方法的声明中一般被Part
、Body
、PartMap
修饰)的对象 –> HTTP Request BodystringConverter(Type type, Annotation[] annotations, Retrofit retrofit)
返回将某种类型转化为
String
的Converter
,某种类型(在接口方法的声明中一般被Field/FieldMap
、Header/HeaderMap
、Query/QueryMap
、Path
修饰) –> String 。因为HTTP 1.1
的 URL / Body / Header 是建立在字符串上的
对于不能/不想处理的数据类型,直接返回 null 就可以了(这也是这些方法的默认实现)。Retrofit 将继续查找适用的
Converter
或者采用一个默认实现。
BuiltInConverters.java
- VoidResponseBodyConverter.class
- RequestBodyConverter.class
- StreamingResponseBodyConverter.class
- BufferingResponseBodyConverter.class
- ToStringConverter.class
CallAdapter.java
比如我们本来只能写返回
Call<Foo>
这样的方法,但是在CallAdapter
(RxJava2CallAdapterFactory
,'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
)的帮助下,我们可以写返回Observable<UsersResponse>
这种的方法。同样有个名为
Factory
的内部类
T adapt(Call<R> call); /* Call<R> --> Foo<R> */
返回一个真正执行(delegate,代理)这个 Call
的实例。比如:
1 |
|
Type responseType();
举个简单的例子,如果接口声明的是 Call<Foo>
,那么这里应该返回 Foo
Retrofit 内置的两个
CallAdapter
,都有这样的代码:
1 | if (getRawType(returnType) != Call.class) { |
意味着默认情况下仅仅能处理 Call<Foo>
这种返回值的接口方法
DefaultCallAdapterFactory.java
创建那种
Adapter
,就是 I/O 和 Callback 执行在同一个线程上那种由于是这里的 I/O 几乎等于网络请求,所以 Android 一般情况下是不会用到这个的。
ExecutorCallAdapterFactory.java
这个类的
adapt(...)
方法将 call 外包给自己的内部类:ExecutorCallbackCall
看到这个
Executor
,em……, 没错,就是java.util.concurrent.Executor
!
四、Retrofit、Platform
##Retrofit.java
Retrofit , Retrofit, Retrofit
一切的入口,Retrofit 家的门面
- 构造函数
1 | Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl, List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories, boolean validateEagerly); Executor callbackExecutor, |
public Builder newBuilder()
em……
new Retrofit.Builder().build()
就是Retrofit
了 。public <T> T create(final Class<T> service)
根据接口信息使用反射生成对应的对象,要求
service.isInterface()
并且不能继承其他接口。
private void eagerlyValidateMethods(Class<?> service)
如果
validateEagerly
为true
,Retrofit将在反射之前来验证并加载接口中的方法。ServiceMethod<?, ?> loadServiceMethod(Method method)
将
java.lang.reflect.Method
加载为retrofit2.ServiceMethod
。callAdapter 相关
1
2public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations);
public CallAdapter<?, ?> nextCallAdapter( CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations);converter 相关
1
2
3
4
5
6
7
8
9
10
11
12
13// a naive getter
public List<Converter.Factory> converterFactories();
// 根据参数查找一个合适的 Converter
public <T> Converter<T, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations);
public <T> Converter<T, RequestBody> nextRequestBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations);
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations);
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations);
public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations);getters 相关
1
2
3
4
5public HttpUrl baseUrl();
public okhttp3.Call.Factory callFactory();
public List<CallAdapter.Factory> callAdapterFactories();
public List<Converter.Factory> converterFactories();
public Executor callbackExecutor();
简单看下
create
方法:
1 | public <T> T create(final Class<T> service) { |
Platform.java
不同的平台有不同的行为,上面提到的
adapter
和converter
等细节方面也是存在差异的。比如 Android 平台在系统层面上限制在 UI 线程上进行网络请求。这个类有两个内部类:
Java8 extends Platform
和Android extends Platform
对于 Java8,跟 callback 有关的是默认实现:
1 | Executor defaultCallbackExecutor() { |
而对于 Android,对应的实现则是这样的:
1 | public Executor defaultCallbackExecutor() { |
对着代码中嵌入的文档,和胡猜各种命名,终于把这个项目捋下来了。
可能是市面上相当详细全面的一篇了,当然很多地方还是不够详细。因为代码实在是不少,贴进来肯定是一篇“巨作”。但是结构还算清晰,如果你也感兴趣,打开你的 Android Studio / IntelliJ Idea 也来看看吧!
Ref:
via boileryao
Happy coding :)