Retrofit源码解析

Retrofit 介绍

官方介绍:

Type-safe HTTP client for Android and Java by Square, Inc.

大致意思就是说,Retrofit 是 Square 公司开发的在 Android 和 Java 上都可以使用的类型安全的 HTTP 客户端。
Retrofit 可以和 RxJava,Gson,OkHttp,等等库结合使用,这也是 Retrofit 这库本身的作用,就是将其他优秀的融合到一起,来实现一个优雅的网络请求库。

ps: 这篇博客的创建日期为 2017-03-16 于 2018-8-26 进行了翻新。里面部分的代码是老版中的。

Retrofit 基本用法

先来看看 Retofit 的基本用法,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//获取服务列表的接口
public interface ServiceService {

@FormUrlEncoded
@POST("service/GetServiceList.do")
Call<ServiceListBean> getServiceList(@Field("c") String c, @Field("status")String status, @Field("page")String page, @Field("limit") String limit);

}

//MainActivity.java
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
//添加解析器的具体实现,主要负责对服务器返回的 Json 转换成 JavaBean
.addConverterFactory(GsonConverterFactory.create())
.build();
ServiceService service = retrofit.create(ServiceService.class);
Call<ServiceListBean> list = service.getServiceList("221", "1", "1", "10");

//调用接口
list.enqueue(new Callback<ServiceListBean>() {
@Override
public void onResponse(Call<ServiceListBean> call, Response<ServiceListBean> response) { }

@Override
public void onFailure(Call<ServiceListBean> call, Throwable t) { }
});

上面就是Retrofit 默认的使用,当然这里使用了Gson的解析器需要在 app 的 build.gradle 中添加 compile 'com.squareup.retrofit2:converter-gson:2.2.0' ,主要是方便把 Json 转换成 JavaBean ,那么我先从 Retrofit 的 Builder 开始分析。

Retrofit 源码解析

Retrofit 最具魅力的地方就是他的可扩展性,内部使用了很多设计模式,对学习设计模式很有帮助,那就从上面的 Demo 中的创建过程开始,一步步的分析下 Retrofit 是怎么实现的吧~。

Retrofit 的构建 「Builder 模式」

其核心思想是将一个“复杂对象的构建算法”与它的“部件及组装方式”分离,使得构件算法和组装方式可以独立应对变化;复用同样的构建算法可以创建不同的表示,不同的构建过程可以复用相同的部件组装方式。 - by 百度百科

上面是百度百科对 23 种设计模式中的创建者模式的描述,通过这段描述我们可以看出,所谓的创建者模式是用来创建对象的,这个时候可能有人要问了,创建个对象为啥还要用啥设计模式,直接 new 不就可以了。诚然,在创建普通对象或者稍微复杂点的对象,我们使用 new 的方式好像并没用上面问题,但是如果碰见了要创建很复杂的对象的时候我们该怎么办呢?具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//创建对象最简单的方式
SimpleObject simple = new SimpleObject();

//稍微赋值点的对象
//通过构造函数或者 setter 来创建
Phone phone = new Phone(money);
// or
Phone phone = new Phone().setMoney(money);


//那么遇见很复杂的对象呢?
HangMu hangmu = new HangMu(xxx,xxx,xxx,xxx,xxx, ... ,xxx);
//or
HangMu hangmu = new HangMu().setXXX().setXXX() ... setXXX();

通过上面的代码,我们可以看到,如果构建一般的对象,是用 new 的方式很轻松。但是如果遇见非常复杂的对象,使用 new 的方式明显是不理智的,所以可以使用 setXXX 的方法,不过呢有些对象在构建的时候是必须要传入固定的参数,这也就是构造函数存在的意义,即在构建这个对象的时候,一定需要传入构建需要用到的参数。

参数很多可以使用 setXXX 的方法,但是我们并不能知道哪些对象是必须要设置的,哪些对象是可以不用设置的,并且在一些的对象中,有一些参数是有默认设置的,就好比多个构造函数重载,通过重载不同的构造器从而实现一些默认参数的定义。上面说了直接通过构造函数来创建一个复杂的对象是不理智的方法,用 setXXX 的方式又不能明确的指定哪些参数是必须药传参数,哪些参数是不是必须要传的参数,所以这个时候就有了 Builder 模式,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class ComplexObject(){

private Object primaryParam1

private Object primaryParam2

private Object secondaryParam1

private Object secondaryParam2

private ComplexObject(Builder builder){
primaryParam1 = builder.getParimaryParam1
//省略重复的代码...
}

public static final class Builder {

private Object primaryParam1

private Object primaryParam2

private Object secondaryParam1

private Object secondaryParam2

// getter or setter

public ComplexObject build(){
if(primaryParam1 == null){
//报错:必要参数必须要设置
}
if(primaryParam2 == null){
//报错:同上
}
if(secondaryParam1 == null)
secondaryParam1 = DefaultSecondaryParam1()
if(secondaryParam2 == null)
secondaryParam2 = DefaultSecondaryParam2()
return ComplexObject(this)
}
}
}

上面就是 Builder 模式的实现,其实 Builder 模式还有很多不同的实现版本,不过大体的思路是一样的,下面我们就来看下,Retrofit 是怎么定义它的 Builder 的,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//Retrfit.Builder.java
//从类的名字就能知道,Retrofit 内部使用了构建者模式,主要是将 Retrofit 的创建简单化.
public static final class Builder {
//Platform 类主要是一些平台相关的信息。主要包含了Android 和 Java 在不同的平台调用不同的逻辑
private final Platform platform;
//OkHttp 中的类
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;

Builder(Platform platform) {
this.platform = platform;
//这里,默认用到了一个叫 BuildtInConverters 的类作为默认的解析器。
converterFactories.add(new BuiltInConverters());
}

public Builder() {
this(Platform.get());
}

//主要是通过另外一个 Retrofit 构建一个新的 Retrofit。
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
converterFactories.addAll(retrofit.converterFactories);
adapterFactories.addAll(retrofit.adapterFactories);
// Remove the default, platform-aware call adapter added by build().
adapterFactories.remove(adapterFactories.size() - 1);
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}

/**
* The HTTP client used for requests.
* <p>
* This is a convenience method for calling {@link #callFactory}.
*/
//设置callFactory
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}

/**
* Specify a custom call factory for creating {@link Call} instances.
* <p>
* Note: Calling {@link #client} automatically sets this value.
*/
//设置callFactory
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}

/**
* Set the API base URL.
*
* @see #baseUrl(HttpUrl)
*/
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
//封装HttpUrl对象,这个HttpUrl对象中记录了url中的很多信息,比如协议,端口号,用户名,密码,主机名称,等等,具体实现在OkHttp中。
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}

/**
* 作用同上
*/
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
//这里强制要求 baseUrl 必须是 / 结尾,不然会抛出异常。
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}

//添加解析器对象
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}

// 中添加 调用适配器
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}

//设置线程池的实现 Android 和 Java 分别有不同的实现
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}

//此属性可以设置 ServiceMethod 的加载机制
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}

//构建 Retrofit 对象
public Retrofit build() {
//BaseUrl 是必须要设置的
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}

//默认使用 OkHttp3 的 CallFactory
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}

//默认使用 MainThreadExecutor , 内部一个MainLooper 的 Handler。
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}

//设置默认的callAdapter
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

// 设置 converterFactory,其主要作用就是将结果转换成想要的对象,比如: Gson 就可以把 返回的 json 转换才 java 中的对象
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

//创建 Retrofit 对象
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
}

上面的代码就是Retrofit的构建过程,其中主要包含了一些参数,比如 BaseUrl,Converter,CallAdapter,CallBackExecutor,等等…其中有部分参数都是有默认的实现,从这些参数的定义,得出其中很多地方都是可以自定义的,比如:解析器,调用适配器,都做成了可扩展的,可以使用不同的方式去实现,并且 Retrofit 自身也给出了默认的实现。

Retrofit.create() 「代理模式」

上面看完 Retrofit 的 Builder 模式,下面在来看看 Retrofit 的代理模式,可以说代理模式是 Retrofit 实现网络请求最基本的条件。

首先看看代理模式的定义:

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 - by 百度百科

上面说到,控制一个对象的访问,首先说说什么是对象的访问,在上文中对象的访问可以看做是调用这个对象的方法,或者对这个对象的属性 get 或者 set 操作,这些都可以看做是对这个对象的访问。

那么是叫做控制一个对象的访问呢?换句话说我们为什么要控制一个对象的访问?原因很简单,在开发中经常会遇到一些经常按照一定规律调用的方法,比如在访问流对象的时候,我们需要先调用 open() 方法,然后在最后调用一下 close() 方法,我们可以通过对这中间执行的操作进行”代理”,然后在被代理的对象像被调用之前先调用一下 open() 在被代理对象被调用完之后在调用一下 close(),这样我们就把这些有规律的操作给封装了起来,就没必要每个地方都写一遍。

下面我们来看看具体代码是怎么写的,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class StreamProxy implements Stream {

private Stream proxy;

public Stream(Stream proxy){
this.proxy = proxy
}

@Override
public String readFile2String(String path) {
openStream() //打开数据流
String result = proxy.readFile2String(path);
closeStream() //关闭数据流
return result;
}

}

public interface Stream {

String readFile2String(String path);

}

public class FileStream implements Stream {

@Override
public String readFile2String(String path) {
//进行读文件的操作,但是不使用 open 和 close
return "文件内容"
}

}

// 使用
Stream fileStream = new StreamProxy(FileProxy())
fileStream.readFile2String("xx/xx.txt")

如上代码一样,算是代理模式的基本实现,可以看到,代理类 (StreamProxy) 需要实现被代理对象的接口,当然前提就是,如果我们希望代理某个类,那么这个类一定要有一个接口,这个是 Java 实现代理模式的必要条件。

上面的代理模式非常的方便,当我们调用 readFile2String() 的时候再也不用调用上面 open() 和 close() 方法了,但是有一个很蛋疼的地方,就是我们的代理类必须要实现被代理类的接口,这就等于相同的接口我们实现了两次,明显是非常不划来的,那么有没有什么办法可以省去这个操作的,就是我们代理类必须重复的实现一次被代理类的接口也能代理被代理类的所所有方法。方法就是使用 Java 提供的一个叫做 Proxy 的类,下面来看看这个类是怎么使用的,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class FileStreamInvocation implements InvocationHandler {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("readFile2String") ) {
System.out.println("Open Stream");
Object result = method.invoke(proxy, args);
System.out.println("Close Stream");
return result;
}
return null;
}
}

//使用
Stream proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Stream.class}, new FileStreamInvocation())

String result = proxy.readFile2String("xxx/xxx.txt")

上面就是 Java 里面 Proxy 这个类的作用,这个类可以动态 (在程序执行的时候) 的改变一些类的执行,为什么 Java 要提供这么一个类呢?原因和 Java 这个语言的特性有关,我们都知道 Java 是一个门静态强类型的语言,简而言之就是不能再程序执行的时候去改变或是插入一些别的操作。

而有了 Proxy 这个类之后就不一样的,借助这类我们能在一个对象的任意操作上定义自己的逻辑,从而来达到在程序运行的时候根据一些参数来改变代码的执行结果。

Retrofit 就是一个典型的例子,我们先想想为什么 Retrofit 要使用代理模式来设计?首先 Retrofit 是一个能够实现实现网络请求的库,为什么要说是能够实现?因为如果我们想要在 Android 里面执行网络请求的操作,可以用诸如:HttpUrlConnection,Volley,OKHttp 等等之类的库,但是这些库有个很大的弊端,那就是网络请求的执行一般都是很模板化的,比如一个网络请求的执行大概分为下面几步:

  1. 创建求对象
  2. 创建参数对象
  3. 使用请求对象发起请求并把参数对象传入
  4. 在回中解析请求对象返回的结果

一个完成的网络请求操作,差不多就是由上面 4 步组成,一个 APP 里面肯定不止一个网络请求,所有就会存在很多相同的代码,也就是会出现很多上面这 4 步操作。

这个时候就该想个办法将上面这些模板化的操作封装起来,尽量减少这些相同的代码。Proxy 这个时候作用就体现出来了,具体是怎么封装,我们来看看那 Retrofit 的源码就知道了,源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//create 方法,用来创建 Proxy d对象
public <T> T create(final Class<T> service) {
//检查接口是否合格
Utils.validateServiceInterface(service);
//默认为 false
if (validateEagerly) {
eagerlyValidateMethods(service);
}

return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();

@Override public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 如果调用的 Object 中的而方法,就不处理。小技巧
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//判断是否是默认方法( Defalut Method ),默认方法是 Java8 中的特性,就是接口里面可以声明默认方法。
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//下面就是重点了,Retrofit 真正的逻辑就是下面这几行代码。
//这个方法暂时先分析到这,因为样分析下面的方法需要设涉及到 CallAdapter 这个类,所以要先分析下 CallAdapter 这个类
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}

//代码目录:Utils.java
//检测接口定义是否合格
//1. 必须要是接口 不能是类
//2. 这个接口不能继承别的接口
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}

if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}

//加载ServiceMethod
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//第三方库的老套路,缓存获取
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;

//防止多线程重复创建
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//没有缓存,创建一个新的并添加到缓存里面。
//ServiceMethod 对应的就是我们在前面接口中声明的方法的封装对象。
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}

上面的 create() 方法就是 Retrofit 的核心方法,之前我们说了 Retrofit 为了尽量让重复的代码减少,使用代理模式,帮我们把网络请求操作给”动态”的组装起来。

组装的内容大概分为下面几类:

  1. 请求的参数
  2. 请求的发起
  3. 请求结果的解析

通过 Retrofit 这一顿操作之后,我们只需要:

  1. 定义请求的参数 -> Retrofit 帮我们把参数设置给请求
  2. 调用请求方法 -> Retrofit 帮我们把我们的调用变成 OKHttp 的调用
  3. 接收结果 -> Retrofit 通过他的转换器提前先帮我们把结果转换一次

除了能帮我们省略重复代码之外,还可以起到一定解耦的效果,因为我们要使用 Retrofit 就必须把接口定义成一个一个的接口,接口可以解耦的利器,所以 Retrofit 帮我们把请求的定义和逻辑处理进行了解耦.

Converter.Factory 和 CallAdpater.Factory 「工厂模式」

上面说完代理模式,下面再来说说工厂模式,这个模式在一些优质的类库里面广泛应用,Retrofit 也不例外,至于原理,我们后面再说,还是来样子,让我们先来看看工厂模式是一个什么样的模式,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
interface Result {
void action();
}

abstract class Factory {

Result createResult();
}

class AResult implements Result {

@override
void action() {
System.out.println("我是 A 产品");
}
}

class BResult implements Result {

@override
void action() {
System.out.println("我是 B 产品");
}
}

class AFactory implements Factory {

@override
void create() {
return AResult();
}
}

class BFactory implements Factory {

@override
void create() {
return BResult();
}
}

//使用
Result aResult = AFactory().create()
Result bResult = BFactory().create()

上面就是工厂模式在 Java 中的定义,注意这里使用的抽象工厂模式,这个模式和普通的工厂模式有点区别,不过作用是一样的。从整体上看会感觉工厂模式非常鸡肋,为了创建一个对象,需要额外的声明一堆别的类。乍一看好像绝对没什么卵用,可是在一些场景下,这种模式可以带来奇效,具体带了什么奇效,我们下面来来工厂模式在 Retorfit 中的使用就知道了。

在 Retrofit 构建的时候,涉及到两个可配置的类。一个叫CallAdapter,另一个叫Converter。
其中CallAdapter负责结构的返回类型,即我们上面在定义 Service 的时候,方法的返回值,上面我们用的是Call<ServiceListBean>,这里的Call是可以我们自定义的,如 RxJava2 实现的 RxJava2CallAdapterFactory ,具体的实现这里不做分析,但是这里无论是 RxJava2 RxJava2CallAdapterFactory 还是 Retrofit 默认的实现 ExecutorCallAdapterFactory ,都是继承至 CallAdapter.Factory,具体代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//CallAdapter interface
//这里有两个泛型,其中 T 这个泛型指定的就是请求返回值的类型,默认是 Call,注意这里的 Call 并不是 OKHttp 的 Call,而是 Retrofit 中定义的 Call 接口。
//而这个名为 R 的泛型只能是 Object,因为在 Retrofit 的 create() 方法中写死了。
public interface CallAdapter<R, T> {

// 返回类型 Call ResponseBody Observable 等等....
Type responseType();

//这个方法会在 create 中调用
T adapt(Call<R> call);

abstract class Factory {

//通过 return 返回 CallAdapter 的具体实现。
public abstract CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);


protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}

protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}


// Retrofit 默认实现的 ExecutorCallAdapterFactory
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
//线程池
final Executor callbackExecutor;

ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
//获取泛型中的类型,上面Demo中获取的就是ServiceListBean
final Type responseType = Utils.getCallResponseType(returnType);
//new 一个CallAdapter 返回
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}

@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}

//实现 Call接口 具体的调用走这个类,比如上面 Demo 中的 enqueue 方法。
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;

//其实这个类知识一个空壳,具体的实现在 delegate 对象中。
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}

@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");

delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
//这里的 CallBackExecutor 在 Android 里面是一个 UI 线程的 Executor
//所以我们可以在回调里面更新 UI
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}

@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
//失败的回调
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}

//是否执行
@Override public boolean isExecuted() {
return delegate.isExecuted();
}

//执行
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}

//取消
@Override public void cancel() {
delegate.cancel();
}

//是否已经取消
@Override public boolean isCanceled() {
return delegate.isCanceled();
}

//Clone
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}

//请求
@Override public Request request() {
return delegate.request();
}
}
}

上面的代码有点绕,不过理清关系之后还是很好理解的,上面我们说到了抽象工厂模式中的产品和工厂都是抽象的,对应到 Retrofit 中就成了这样:

  • 产品 -> 请求的返回值 -> CallAdapter -> ExecutorCallAdapterFactory
  • 工厂 -> 创建请求返回值的过程 -> CallAdpater.Factory -> 直接返回 CallAdapter 的匿名内部类

工厂和产品是意义对应的,之所以产品和工厂都抽象的是因为,产品的创建流程和产品本身都是可变的,所以都要定义成抽象的,就像在 Retrofit 中,请求的返回值类型和返回值类型的创建流程一样。

下面我们来看看 Retrofit 在默认情况下的返回值类型是怎么创建的,至于返回值类型的创建流程(这里可能有点绕口,这里的流程指的是在创建返回值类型之前的流程,而返回值类型的创建是指返回值本身的创建),在 Retrofit 的默认实现中,是直接创建了了 CallFactory 的匿名内部类,所以没什么好分析的。

上面说到在 ExecutorCallbackCall 类中,真正的实现其实是 OkHttpCall 这个类,上面我们提到了 Retrofit 中也定一个名为 Call 的接口,这个接口和 OKHttp 中的 Call 如出一辙,而这个 OKHttpCall 的类就是帮助我们将 Retorfit 中的 Call 转换成 OKHttp 中的 Call 的,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//下面代码摘自 Retorfit 2.4.0 和上面的源码可能都点出入
//首先看看 OKHttp 中的 Call 和 Retorfit 中的 Call 有什么区别

//OKHttp Call
public interface Call extends Cloneable {

Request request();

Response execute() throws IOException;

void enqueue(Callback responseCallback);

void cancel();

boolean isExecuted();

boolean isCanceled();

Call clone();

//OKHttp 中的工厂
interface Factory {
Call newCall(Request request);
}
}

//Retrofit Call
public interface Call<T> extends Cloneable {

Request request();

//注意这个 Response 也是 Retrofit 中的,而不是 OKHttp 中的。
Response<T> execute() throws IOException;

void enqueue(Callback<T> callback);

boolean isExecuted();

void cancel();

boolean isCanceled();

Call<T> clone();

}

可以看到 OKHttp 中的 Call 和 Retrofit 中的 Call 基本上一毛一样,未读的区别就在于那个泛型,为什么 Retrofit 中会多个泛型呢?很简单,上面说到 Retrofit 除了能发起网络请求以外,还有一个操作就是对结果解析,这的解析很多种,不过用的最多的就是将 JSON 转出 Java 对象,所以这里的泛型其实就是在后面做转换的时候用到的。

下面在来看看 OKHttpCall 这个类,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
//实现 Call 接口
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;
private final @Nullable Object[] args;

private volatile boolean canceled;

@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;
@GuardedBy("this")
private @Nullable Throwable creationFailure;
@GuardedBy("this")
private boolean executed;

OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}

@SuppressWarnings("CloneDoesntCallSuperClone") // We are a final type & this saves clearing state.
@Override public OkHttpCall<T> clone() {
return new OkHttpCall<>(serviceMethod, args);
}

@Override public synchronized Request request() {
okhttp3.Call call = rawCall;
if (call != null) {
return call.request();
}
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw new RuntimeException("Unable to create request.", creationFailure);
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
try {
return (rawCall = createRawCall()).request();
} catch (RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
} catch (IOException e) {
creationFailure = e;
throw new RuntimeException("Unable to create request.", e);
}
}

@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");

okhttp3.Call call;
Throwable failure;

synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;

call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}

if (failure != null) {
callback.onFailure(this, failure);
return;
}

if (canceled) {
call.cancel();
}

call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}

try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}

@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}

private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}

@Override public synchronized boolean isExecuted() {
return executed;
}

@Override public Response<T> execute() throws IOException {
okhttp3.Call call;

synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;

if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}

call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}

if (canceled) {
call.cancel();
}

//解析结果
return parseResponse(call.execute());
}

//创建 OKHttp 中的 Call 对象
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}

//解析结果
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();

//剔除 Response 中的内容,方便向上层传递
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();

int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
//http code 200,500 等等
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}

if (code == 204 || code == 205) {
//204 或者 205 表示数据没有更新,所以不会把请求体传递给上层
rawBody.close();
return Response.success(null, rawResponse);
}

ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//解析服务器返回的结果
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
catchingBody.throwIfCaught();
throw e;
}
}

public void cancel() {
canceled = true;

okhttp3.Call call;
synchronized (this) {
call = rawCall;
}
if (call != null) {
call.cancel();
}
}

@Override public boolean isCanceled() {
if (canceled) {
return true;
}
synchronized (this) {
return rawCall != null && rawCall.isCanceled();
}
}

//没有内容的 ResponseBody
static final class NoContentResponseBody extends ResponseBody {
private final MediaType contentType;
private final long contentLength;

NoContentResponseBody(MediaType contentType, long contentLength) {
this.contentType = contentType;
this.contentLength = contentLength;
}

@Override public MediaType contentType() {
return contentType;
}

@Override public long contentLength() {
return contentLength;
}

@Override public BufferedSource source() {
throw new IllegalStateException("Cannot read raw response body of a converted body.");
}
}

//将 OkIO 中报的错 Cache 主,把这些异常和 Retrofit 中的异常区别开来
static final class ExceptionCatchingRequestBody extends ResponseBody {
private final ResponseBody delegate;
IOException thrownException;

ExceptionCatchingRequestBody(ResponseBody delegate) {
this.delegate = delegate;
}

@Override public MediaType contentType() {
return delegate.contentType();
}

@Override public long contentLength() {
return delegate.contentLength();
}

@Override public BufferedSource source() {
return Okio.buffer(new ForwardingSource(delegate.source()) {
@Override public long read(Buffer sink, long byteCount) throws IOException {
try {
return super.read(sink, byteCount);
} catch (IOException e) {
thrownException = e;
throw e;
}
}
});
}

@Override public void close() {
delegate.close();
}

void throwIfCaught() throws IOException {
if (thrownException != null) {
throw thrownException;
}
}
}
}

执行观察 OKHtpp 这个类,其实就会发现,这个类有点像我们前面说的代理类,里面的每个方法里面其实什么逻辑都没有,有的只是调用 rawCall 这个对象中对应的方法,而这个 rawCall 就是 OKHttp 中的 Call,这么一看这个名为 OKHttpCall 的类有点像是 OkHttp Call 的代理类,既然是代理类,那么肯定有一些额外的操作,那就是我们前面说的将返回结果进行转换。

结果的转换在 parseResponse() 这个方法中,最终会调用 ServiceMethod 类中的 toResponse() 方法,方法的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//ServiceMethod<R, T>.java
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}

//Converter.java
public interface Converter<F, T> {
T convert(F value) throws IOException;

abstract class Factory {

public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}

public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}

public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}

protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}

protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}

在 ServiceMethod 的 toResponse() 方法中调用了 responseConverter 的 convert() 方法,这个名为 Converter 的类有两个泛型分别是 R 和 T,其中 R 是死的就是 ResponseBody 类型,而这个 T 就是我们前面在 OKHttp 传入的那个 T 类型。

很显然这个 Converter 也是一个工厂模式的实现,Retorfit 中默认的实现叫做 BuiltInConverters,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
final class BuiltInConverters extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}

@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}

//处理 Call<Void>
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();

@Override public Void convert(ResponseBody value) {
value.close();
return null;
}
}

//解析 Request
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

@Override public RequestBody convert(RequestBody value) {
return value;
}
}

//@Streaming 注解
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

@Override public ResponseBody convert(ResponseBody value) {
return value;
}
}

//Call<ResponseBody>
static final class BufferingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();

@Override public ResponseBody convert(ResponseBody value) throws IOException {
try {
// Buffer the entire body to avoid future I/O.
return Utils.buffer(value);
} finally {
value.close();
}
}
}

//解析 @Field,@FieldMap,@Header,@HeaderMap,@Path,@Quer,@QueryMap
//总而言之就是所有注解中传入的字符串
static final class ToStringConverter implements Converter<Object, String> {
static final ToStringConverter INSTANCE = new ToStringConverter();

@Override public String convert(Object value) {
return value.toString();
}
}
}

通过这个类,我们可以得出如果在默认情况下使用 Retrofit,请求接口方法的返回值为 Call,而 T 的类型只能是 ResponseBody 类型或者 Void 类型。其他类型是不支持的

整合

上面我们分别分析了 Builder 模式,Proxy 模式,和 Factory 模式在 Retrofit 中的应用,回够头来在看看 Retrofit 中的 create() 方法你会发现就一目了然了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

//Retorfit 对象本身是通过 Build 模式创建的
public <T> T create(final Class<T> service) {
//一些配置
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//代理模式,对定义的接口的方法调用进行拦截
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();

@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
//小技巧
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//ServiceMethod 对象就是通过拦截的参数创建出来的
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//OKHttpCall是个代理类,而被代理的类就是 OKHttp 中的 Call,而这个 Call 就是通过
//ServiceMethod 对象创建出来的
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//adapt() 方法调用了 CallAdapter 的 adapt()
return serviceMethod.adapt(okHttpCall);
}
});
}

Plus

上面我们分析的是 Retrofit 默认给出的一些默认实现,很显然 Retrofit 之所以大费周章的这么设计,肯定是为了方便其他的库来扩展用的。在我看来,一个库好用不好用,就取决于这个库的扩展能扩展到上面样的程度。

通过上面的分析,我大概已经知道了 Retrofit 能扩展的程度。具体如下

  1. 通过扩展 CallAdapter 我们可以对接口的返回值进行扩展。
  2. 通过扩展 Converter 我们可以对接口返回的数据与真实之间的转换进行扩展。

RxJava CallAdapter

要说最常用的 CallAdapter,当属 RxJava2CallAdapter,这个 CallAdapter 可以将我们接口返回的数据转换成一个 RxJava 的数据流,我们可以借助 RxJava 的特性对这个数据流做任意的操作,比如最最最常用的就是使用 RxJava 的 zip() 方法可以很轻松的就是实现将多个接口的返回结果组合成一个结果。关于 RxJava 的使用这里不做过多介绍,下面我们来看看 R小Java2CallAdapter 是怎么实现的,具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {

public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null, false);
}

public static RxJava2CallAdapterFactory createAsync() {
return new RxJava2CallAdapterFactory(null, true);
}

@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJava2CallAdapterFactory(scheduler, false);
}

private final @Nullable Scheduler scheduler;
private final boolean isAsync;

private RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {
this.scheduler = scheduler;
this.isAsync = isAsync;
}

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//API 接口中函数返回的类型
Class<?> rawType = getRawType(returnType);

if (rawType == Completable.class) {
//API 接口中函数的返回值类型为 Completeable,此类是不需要泛型的,所以直接返回 Void 类型
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}

boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
//如果 API 接口函数中的返回值类型不是 RxJava 中的类型,就直接返回 null
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}

boolean isResult = false;
boolean isBody = false;
Type responseType;
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}

Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
//Response 必须要指定泛型
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
//通 Response,Result 也必须要指定泛型
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
//直接传入其他类型的泛型,如 Observable<User>,这个时候 isBody 为 true
responseType = observableType;
isBody = true;
}

//创建 RxJava2CallAdapter 类型的实例
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
}

首先是 CallAdapter.Factory 的实现类 RxJava2CallAdapterFactory,首先这个类提供了静态的 create() 方法,方便我们创建该类的实例,其中有个叫 createWithScheduler() 的方法,当我们使用此方法创建 Factory 的实例之后,所有的网络请求(被观察者)都会在传入的 Scheduler 的线程中执行。

CallAdapter.Factory 只需要实现一个方法,那就是 get() 方法,用过 RxJava2 的同学应该都知道,RxJava2 中提供了多种被观察类型,比如 Observable,Flowable,Completable 等等,很显然需要在 get() 方法中根据 rawType 即定义在 API 接口中的真实类型来创建不同的 CallAdapter。通过前面的分析,我们知道 Retrofit 是可以指定多个 CallAdapter 的,那么问题来了,Retrofit 是怎么确定使用哪一个 CallAdapter 的呢?答案就在 get() 方法中的 return null 那里,在 Retorfit 遍历 CallAdapter 集合并调用每个 CallAdapter 的 get() 方法的时候,会判断方法的返回值是不是 null,如果是 null 就表示这个 CallAdapte 不支持当前所以调用的函数的返回值类型,如果都返回 null 就会直接抛出异常,即表示定义函数 Retorfit 无法解析。具体参考 Retrofit 中的 nextCallAdapter() 方法。

如果确定了 rawType 是 RxJava2 中的类型,就会针对其中泛型做处理,比如我们可以声明函数的返回值类型为 Observable<Response> 这个 Response 是 Retrofit 的 Response,还可以使用 Observable<Result>,这个 Result 是 RxJava2CallAdapter 里面提供的一个类,这两个类用的不是很多,用的最多的返回值类型还是 Observable

需要注意的是,如果在 API 接口函数的返回值的泛型为 Result 或是 Response 的时候,isBody 是为 false 的。紧接着会创建 RxJava2CallAdapter 类型的实例。具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
private final Type responseType;
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
private final boolean isResult;
private final boolean isBody;
private final boolean isFlowable;
private final boolean isSingle;
private final boolean isMaybe;
private final boolean isCompletable;

RxJava2CallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync,
boolean isResult, boolean isBody, boolean isFlowable, boolean isSingle, boolean isMaybe,
boolean isCompletable) {
this.responseType = responseType;
this.scheduler = scheduler;
this.isAsync = isAsync;
this.isResult = isResult;
this.isBody = isBody;
this.isFlowable = isFlowable;
this.isSingle = isSingle;
this.isMaybe = isMaybe;
this.isCompletable = isCompletable;
}

@Override public Type responseType() {
return responseType;
}

@Override public Object adapt(Call<R> call) {
//同步 or 异步
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);

Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}

//使用 createWithScheduler() 方法创建 RxJava2CallAdapter
//会自动帮我们调用 subscribeOn() 方法
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}

//通过参数将 Observable 转换成 Flowable,Single,Maybe 以及 Completable
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
}

RxJava2CallAdapter 实现 CallAdapter 接口,在 ResponseType 方法中返回从 RxJava2CallAdapterFactory 传入的 responseType,即定义在 API 接口函数中的返回值类型的泛型。然后就是 adapt() 方法,首先同步和异步使用的 Observable 是不一样的,区别在于执行请求的时候是调用 execute() 方法还是 enqueue(),需要注意的是,在这两个的 Observable 类中,都把请求和数据流进行了绑定,什么意思呢?先来看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static final class CallDisposable implements Disposable {
private final Call<?> call;
private volatile boolean disposed;

CallDisposable(Call<?> call) {
this.call = call;
}

@Override public void dispose() {
disposed = true;
//重点在这里
call.cancel();
}

@Override public boolean isDisposed() {
return disposed;
}
}

用过 RxJava 的同学应该知道,我可以借助一些库来实现将 RxJava 的数据流和 Activity 的声明周期进行绑定,这样做的好处就是不会出现 Activity 内存泄漏,在传统的网络请求中,必定会传入一个回调函数,有回调的地方就会有很大几率出现泄漏,所以在我们将 RxJava 数据流和它的回调进行解绑的时候,请求也会跟着取消,这样我们就不用担心在网络不好的情况下,因为重复的操作而浪费资源的情况。

处理完异步和同步的问题,回到 RxJava2CallAdapter 的 adapt() 方法,在方法接着会判断是否是 Result 类型的泛型,如果是 Result 类型的,就会返回 ResultObservable 类的实例,如果 isBody 为 true 就会返回 BodyObservable 类的实例,这里使用了代理模式,将上面的同步 or 异步的 Observable 进一步的做了扩展,具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
final class BodyObservable<T> extends Observable<T> {
private final Observable<Response<T>> upstream;

BodyObservable(Observable<Response<T>> upstream) {
this.upstream = upstream;
}

@Override protected void subscribeActual(Observer<? super T> observer) {
upstream.subscribe(new BodyObserver<T>(observer));
}

private static class BodyObserver<R> implements Observer<Response<R>> {
private final Observer<? super R> observer;
private boolean terminated;

BodyObserver(Observer<? super R> observer) {
this.observer = observer;
}

@Override public void onSubscribe(Disposable disposable) {
observer.onSubscribe(disposable);
}

@Override public void onNext(Response<R> response) {
if (response.isSuccessful()) {
observer.onNext(response.body());
} else {
terminated = true;
Throwable t = new HttpException(response);
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}

@Override public void onComplete() {
if (!terminated) {
observer.onComplete();
}
}

@Override public void onError(Throwable throwable) {
if (!terminated) {
observer.onError(throwable);
} else {
Throwable broken = new AssertionError(
"This should never happen! Report as a bug with the full stacktrace.");
broken.initCause(throwable);
RxJavaPlugins.onError(broken);
}
}
}
}

这里我们只看 BodyObservable,至于 ResultObservable 大同小异,可以看到在 BodyObservable 类中,代理了 upstream 的 subscribe() 方法,在我们传入的 Observer 对象的基础上做了点操作,比如上面就帮我们获取了 respone 的 body(),注意这里的 Response 是 Retrofit 中的。

除了帮我们调用 body() 以外,还帮我们处理了异常,如果请求异常,会调用我们 Observer 的 onError() 方法。

最后在回到 RxJava2CallAdpater 的 adapt () 方法中,在方法的最后,会帮我们把 Observable 转换成我们在 API 接口函数中定义的返回值类型。自此,RxJava2CallAdapter 的源码我们就分析完毕了,可以看到 RxJava 对于我们网络请求来说用处还是很大的,比如会帮我们 cacel 掉请求,并且还会帮我们处理异常情况(HTTP code 不等于 200)。

Moshi Converter

上面是 CallAdapter 的 RxJava 的实现,下面我们再来看看 Converter 的第三方实现,在这里我们拿 Moshi 这个库为例,来看看 Converter 是怎么扩展的。首先说下 Moshi 这个库和 Retrofit 是出自同一家公司,属于亲儿子,所以如果要在 Retrofit 中对请求结果的 json 转成 Java/Kotlin 对象的话,优先使用 Moshi 吧(特别是转 Kotlin 对象)。

和 CallAdapter 一样,Converter 也有一个 Factory,即 MoshiConverterFactory,具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public final class MoshiConverterFactory extends Converter.Factory {
/** Create an instance using a default {@link Moshi} instance for conversion. */
public static MoshiConverterFactory create() {
return create(new Moshi.Builder().build());
}

/** Create an instance using {@code moshi} for conversion. */
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static MoshiConverterFactory create(Moshi moshi) {
if (moshi == null) throw new NullPointerException("moshi == null");
return new MoshiConverterFactory(moshi, false, false, false);
}

private final Moshi moshi;
private final boolean lenient;
private final boolean failOnUnknown;
private final boolean serializeNulls;

private MoshiConverterFactory(Moshi moshi, boolean lenient, boolean failOnUnknown,
boolean serializeNulls) {
this.moshi = moshi;
this.lenient = lenient;
this.failOnUnknown = failOnUnknown;
this.serializeNulls = serializeNulls;
}

public MoshiConverterFactory asLenient() {
return new MoshiConverterFactory(moshi, true, failOnUnknown, serializeNulls);
}

public MoshiConverterFactory failOnUnknown() {
return new MoshiConverterFactory(moshi, lenient, true, serializeNulls);
}

public MoshiConverterFactory withNullSerialization() {
return new MoshiConverterFactory(moshi, lenient, failOnUnknown, true);
}

@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
JsonAdapter<?> adapter = moshi.adapter(type, jsonAnnotations(annotations));
if (lenient) {
adapter = adapter.lenient();
}
if (failOnUnknown) {
adapter = adapter.failOnUnknown();
}
if (serializeNulls) {
adapter = adapter.serializeNulls();
}
return new MoshiResponseBodyConverter<>(adapter);
}

@Override public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
JsonAdapter<?> adapter = moshi.adapter(type, jsonAnnotations(parameterAnnotations));
//这些都是关于 Moshi 的一些设置,和 Retorfit 无关
if (lenient) {
adapter = adapter.lenient();
}
if (failOnUnknown) {
adapter = adapter.failOnUnknown();
}
if (serializeNulls) {
adapter = adapter.serializeNulls();
}
return new MoshiRequestBodyConverter<>(adapter);
}

// ...
}

和 RxJava2CallFactory 类的设计大同小异,可以说基本一样,提供了 create() 创建实例,与 CallAdapter.Factory 不一样的是,Converter.Factory 不是接口,而是一个抽象类,这就说明了我们可以更具我们的需求来重写对应的方法,在这里分别重写 responseBodyConverter() 和 requestBodyConverter() 这两个方法,第一个方法是用来创建解析 HTTP 返回的 body 的 Converter,第二个方法就是用来创建解析 HTTP 请求 body 中的数据的 Converter 的。

接下来看看 ResponseConverter 和 RequestConverter 这两个类,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
final class MoshiResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private static final ByteString UTF8_BOM = ByteString.decodeHex("EFBBBF");

private final JsonAdapter<T> adapter;

MoshiResponseBodyConverter(JsonAdapter<T> adapter) {
this.adapter = adapter;
}

@Override public T convert(ResponseBody value) throws IOException {
BufferedSource source = value.source();
try {
//utf-8_bom 是一个很大坑
if (source.rangeEquals(0, UTF8_BOM)) {
source.skip(UTF8_BOM.size());
}
JsonReader reader = JsonReader.of(source);
T result = adapter.fromJson(reader);
if (reader.peek() != JsonReader.Token.END_DOCUMENT) {
throw new JsonDataException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}

final class MoshiRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");

private final JsonAdapter<T> adapter;

MoshiRequestBodyConverter(JsonAdapter<T> adapter) {
this.adapter = adapter;
}

@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
JsonWriter writer = JsonWriter.of(buffer);
adapter.toJson(writer, value);
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}

可以看到两个类的实现基本差不多,在对 Response 的解析的时候,会忽略掉 UFT_BOM,而且解析 requestBody 的时候,会创建 content-type 为 application/json 的 requestBody。

比起 CallAdapter,Converter 的扩展明显轻松许多。

总结

分析了这么多,上面大概就是 Retrofit 的整体执行逻辑,用到了很多设计模式,就是因为用了很多设计模式,所以 Retrofit 是一个扩展性很好的框架。
其中大概对CallAdapter 和 Converter 这两样东西做了扩展,具体的实现逻辑上面也分析了,总之 Retrofit 是一个使用了很多设计模式的框架,框架的本体并没有实现什么具体的逻辑,比如请求是用的OkHttp,结果的解析可以用Gson,返回结果的封装也可用使用RxJava等等…,自己只负责将这几个东西组合在一起,并使用接口 + 注解的方式来定义服务器的接口,将接口的定义和接口的调用进行了解耦,很推荐在项目中使用。

Retrofit 是一个非常优秀的库(废话),也难怪在 Google 的官方 Demo 中都会时不时看到它的身影,也就导致了我又想重新读一遍它的源码的想法。通过这一次对源码的阅读,对 Retrofit 本身的理解又加深了许多,以前可能只是觉得 Retrofit 可以把接口的定义和接口调用解耦,现在觉得远远不止这么简单。我们可以思考这样一个问题,Retrofit 究竟解决了什么样的问题?

  1. 帮助我们省略了很多很多重复的代码。
  2. 无缝整合其他跟 HTTP 相关的优秀的库。

通过上面这两点,让我对解耦有了新的认识,以前觉得解耦就是将代码分开,现在觉得不仅要把代码分开还要尽量减少重复的代码,并且要考虑代码的可扩展性,而减少重复代码的手段就是使用代理模式,代码的扩展就是使用抽象工厂模式,这两个模式在 Retrofit 中的实现就是很好的例子。

今天是 2018年8月26日,这篇博客的创建日期是 2017年3月16日,过了一年半了,正如很多书中说的那样,随着本身经验的增长,对技术的看法也会有所变化,所以隔断时间重新回味一下会有出出乎意料的收获。