前言

Glide篇RxJava2篇OkHttp篇后,这次轮到了Retrofit。相比前面几篇,这篇要稍短一些,因为Retrofit库本身代码量就不多,它作为一款上层网络框架,主要作用是包装底层网络框架,完成各种数据的转化与适配工作。虽然代码不多,但Retrofit依然用到了大量的设计模式,具有非常好的扩展性,与RxJava2、Gson、OkHttp等主流库可以无缝对接,这也正是Retrofit的魅力所在。本次的分析要点如下:

  • retrofit中的动态代理与完整流程(Proxy、ServiceMethod、OkHttpCall)
  • retrofit中的转换器与适配器(Converter、CallAdapter)

Retrofit中的动态代理与完整流程

先从Retrofit的一个简单例子入手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Retrofit.Builder builder = new Retrofit.Builder();
Retrofit retrofit = return builder
.baseUrl(url)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
GankApis gankService = retrofit.create(GankApis.class);
//GankApis.java
public interface GankApis {
String HOST = "http://gank.io/api/";
@GET("random/data/福利/{num}")
Flowable<GankHttpResponse<List<GankItemBean>>> getRandomGirl(@Path("num") int num);
}

Retrofit的使用还是挺简单的,根据约定的API定义接口,然后通过Builder模式创建Retrofit对象,最后通过create方法生成接口的一个代理对象,通过这个代理对象就可以调用我们定义好的接口方法获取数据了。Builder模式没有什么好说的,其中addCallAdapterConverter的作用后面再谈,那么重点就在这个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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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);
}
//最核心的是下面三行代码
//将method处理成serviceMethod
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//创建okHttpCall并传入方法和参数
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//将OkHttpCall适配成我们需要的Call类型
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
//根据method从缓存取serviceMethod,否则创建serviceMethod并存入缓存
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}

可以看到这里用到了Java自带的Proxy类,这个类提供了动态代理的支持,newProxyInstance方法会生成当前接口的代理类,并返回一个该代理类的实例。正是动态代理技术使我们在代理对象的方法触发时有机会添加额外的逻辑,Retrofit也是利用了这一点,把解析注解,生成request,转化response等一系列每次请求都会涉及的重复工作都封装到了这个代理对象中,我们只需要专注于API接口的编写即可,这也是AOP(面向切面编程)思想的一种体现。

每当我们调用代理对象的方法时,都会触发InvocationHandlerinvoke方法,它会把我们这次调用的方法method和参数args都回调过来,拿到method后首先经过loadServiceMethod方法将它转化成一个serviceMethod对象,转化时会以method为key优先尝试从缓存中获取serviceMethod,进入ServiceMethod这个类的源码

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
//ServiceMethod.java
final class ServiceMethod<R, T> {
ServiceMethod(Builder<R, T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
//处理参数,获得request
Request toRequest(@Nullable Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
//经过converter处理,将原始response.body转化为我们需要的类型
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
}
//省略大量代码
}
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Url) {
//省略
} else if (annotation instanceof Path) {
gotPath = true;
Path path = (Path) annotation;
String name = path.value();
validatePathName(p, name);
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Path<>(name, converter, path.encoded());
} else if (annotation instanceof Query) {
//省略
}
}
}

为了篇幅省略了大量代码,因为该类中的大部分方法都是parseXXX用来做当前method及其参数注解的解析工作,并将解析后的结果存储到自己的成员变量中等待后续使用。除此之外还提供了两个重要方法,toRequesttoResponse,我们请求时使用的request和最后得到的response就是由这两个方法返回的。

toRequest中,请求时用到的每个参数都会交给一个ParameterHandler做处理,它会解析参数的注解(Path,Header,Query,Part等等),并根据注解类型去调用RequestBuilder提供的不同的方法(addHeader、addQueryParam、addPathParam等等)来逐步完成request的构建。

toResponse中则相对简单,直接将原始返回报文response.body经过converter处理成我们需要的类型的对象。

继续回到Retrofit类,在获得serviceMethod后,将它和请求参数一起作为参数创建了一个OkHttpCall对象,OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);如果你之前了解过OkHttp的源码,对Call这个类型一定很熟悉,它是一个已经就绪了的请求任务。OkHttpCall在这里作为一个装饰类,持有真正用做请求的rawCall,而这个rawCall对象就是通过传入的serviceMethod的toRequest方法生成的

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
//OkHttpCall.java
//生成真正用于执行请求任务的Call
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
//异步请求方法
@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) {
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)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
//同步请求方法
@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 {
throw (RuntimeException) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
//同步请求
return parseResponse(call.execute());
}
//本次请求结果经过toResponse(converter)处理后返回
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
//省略部分代码
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
catchingBody.throwIfCaught();
throw e;
}
}

上面的代码虽然比较长,但其实只截取了四个比较重要的方法,createRawCall()生成rawCall,enqueue(Callback<T> callback)执行异步请求,execute()执行同步请求,parseResponse(okhttp3.Response rawResponse)将请求结果经converter处理后返回。OkHttpCall将实际请求交给rawCall来完成,调用了rawCall的相应方法,而同步请求与异步请求已经进入到OkHttp这个库的源码范畴了,这里就不再深入了,感兴趣的话可以看我之前写的OkHttp源码分析

再次回到Retrofit类,最后将OkHttpCall经过callAdapteradapter方法处理后的结果,作为本次方法调用的返回值返回return serviceMethod.callAdapter.adapt(okHttpCall);,到此整个流程结束。对于文章最初的例子而言,此刻将得到一个Flowable<GankHttpResponse<List<GankItemBean>>>对象。

Retrofit中的转换器与适配器

上面虽然走完了整个retrofit的流程,但是有两个关键点还没有细说,其一是toResponse中用到的Converter,其二是最后用到的CallAdapter 。Retrofit作为一款上层的网络框架(底层通常由OkHttp负责)它最主要职责就是自动的为我们做好数据的转化工作,比如将我们定义的基于注解的接口转化为可供底层网络框架使用的request,将收到的原始response转化为我们希望收到的数据类型,Converter和CallAdapter就是完成转化工作的组件之一。同时,这两个接口设计的十分灵活,易于拓展,可以和当今甚至未来的各种库对接,也体现了Retrofit的优势,下面分别来做分析。

Converter

1
2
3
public interface Converter<F, T> {
T convert(F value) throws IOException;
}

以上是Converter接口的定义,可见它很直白的是将一个类型转化为另一个类型,但是我们在编写它的实现类时经常会按照以下形式来定义这个方法

1
2
public RequestBody convert(T value)
public T convert(ResponseBody value)

即将一个具体对象(通常是bean对象)转化为request消息体,或是将收到的原始response消息体转为一个具体对象。如果不依靠retrofit我们通常会用Gson来手动完成序列化与反序列化工作,retrofit官方扩展库已经贴心的为我们准备好了Gson版本的converter-gson,让Gson的解析工作依靠Converter无缝的插入到Retrofit中。除了Gson以外官方还提供了Jackson,Java8,Protobuf等常见数据类型的转换器。

在开头的例子中,我们在Builder模式中加入了GsonConverterFactory.create()这个Converter.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
public final class GsonConverterFactory extends Converter.Factory {
public static GsonConverterFactory create() {
return create(new Gson());
}
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
//提供responseBodyConverter
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
//提供requestBodyConverter
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}

这个工厂类为我们提供了创建responseBodyConverterrequestBodyConverter的方法,在ServiceMethod类执行build方法时会创建converter并保存在自己的成员变量中。

1
2
3
4
5
6
7
8
9
//ServiceMethod.java
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}

其中Type是在ServiceMethod中解析出的我们的目标类型,然后进入GsonResponseBodyConverter的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}

在这里获取响应报文中的json并通过gson转到成我们的目标类型对象,然后返回,这也就是之前toResponse方法中做的实际工作。

通过对GsonConverterFactoryGsonResponseBodyConverter的分析,我们也能总结出,当我们需要自定义Converter时的一般流程。

  • 定义XXXResponseBodyConverter和XXXRequestBodyConverter,通过Factory中传递过来的type,parameterAnnotations,methodAnnotations这些参数在convert方法中完成我们计划中的类型转换
  • 定义XXXConverterFactory,对外提供create静态创建方法,重写requestBodyConverterresponseBodyConverter方法,创建并返回我们需要的具体converter,并且在创建时传入处理时需要的参数。

CallAdapter

如果说Converter主要是针对requestBody与responseBody来做转换工作的话,CallAdapter就是专门针对Call类型的转换了,看下它的接口定义

1
2
3
4
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call);
}

结合上面的接口,我们由Converter得到了理想的R类型,那么接下来就可以通过CallAdapter再得到理想的T类型,这里以官方扩展库中的adapter-rxjava2为例,首先CallAdapter对象也是在ServiceMethod中由Factory创建的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//ServiceMethod.java
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}

然后进入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
//创建工厂时可以指定同步或异步
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);
}
//也可以自己指定一个scheduler,之后会传入subscribeOn操作符,从而确定整个过程所在线程
@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) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
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;
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) { //目标类型为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 { //Response返回的类型与目标类型一致时
//文章开头的示例满足这种情况
//我的目标类型是GankHttpResponse<List<GankItemBean>>
//服务端返回的Response消息体内容也的确是这种类型
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
}

上面注释已经标注的很清晰了

  • Factory支持指定同步请求或异步请求,或在指定scheduler中请求
  • 在get方法中会进行一系列判断,以确定具体的目标类型,为下一步CallAdapter中做转换做准备

然后进入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
//RxJava2CallAdapter.java
@Override public Object adapt(Call<R> call) {
//自定义Observable,分同步与异步两种,相当于数据源
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;
}
//如果指定了scheduler则接一个subscribeOn操作符调度线程
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
//根据之前在Factory中的判断,转换为目标类型后返回
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}

adapt方法中完成了Call到Object的转换,对本例而言是将Call转换为了Flowable。这里以同步场景为例,call传入了CallEnqueueObservable,该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
57
58
final class CallExecuteObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallExecuteObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
//实际发生订阅的地方
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
//由于Call只能执行一次,这里clone一个Call供该Observable使用
Call<T> call = originalCall.clone();
observer.onSubscribe(new CallDisposable(call));
boolean terminated = false;
try {
//开始执行同步请求的地方
//可见在该Observable被订阅时才会发生请求
Response<T> response = call.execute();
if (!call.isCanceled()) {
//结果传递给观察者
observer.onNext(response);
}
if (!call.isCanceled()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!call.isCanceled()) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
private static final class CallDisposable implements Disposable {
private final Call<?> call;
CallDisposable(Call<?> call) {
this.call = call;
}
//取消订阅时也会取消请求
@Override public void dispose() {
call.cancel();
}
@Override public boolean isDisposed() {
return call.isCanceled();
}
}
}

  • 在这里我们终于看到了call.execute();这个在上一节中提到过的实际触发同步请求的方法,它被封装到了subscribeActual方法中,该方法是当前Observer被订阅时会触发的方法,可见在该Observable被订阅时才会发生请求
  • 得到请求结果后会通过observer.onNext(response);将结果传递给下游观察者
  • 在该类中,不仅仅将触发请求与订阅做了绑定,同时还把取消请求与取消订阅做了绑定

到此CallAdapter也分析完了,官方提供了rxjava、rxjava2、java8等多种类型的Adapter,如果不能满足需求我们也可以自己定义CallAdapter,一样是有套路的:

  • 根据目标类型编写CallAdapter的实现类,在adapt方法中完成转化
  • 继承CallAdapter.Factory编写工厂类,在get方法中根据获取到的参数做一些判断处理,依照处理结果创建CallAdapter的实现类对象并返回

最后

Retrofit由于代码量比较少,篇幅相比之前几篇源码分析的文章也要简短不少。但是阅读Retrofit的源码需要对OkHttp和RxJava2的源码有一定的了解,所以我还是建议最后再去分析这款框架。这几款框架也都有共通之处,都为用户预留了拓展接口,想用好这些扩展接口,阅读源码了解其运作原理也是必不可少的:

  • 在RxJava2中我们可以自定义Operator(Observable)
  • 在Glide中我们可以自定义GlideModule
  • 在OkHttp中我们可以自定义Interceptor
  • 在Retrofit中我们可以自定义CallAdapter、Converter

通过实现这些自定义接口,我们可以根据需求场景,把自己的业务逻辑无缝插入到这些框架中,既实现了功能又不会破坏代码整体结构,这才是“优雅”的框架。我们在设计框架时,也应该充分借鉴这一点,为用户预留充足的自定义空间,这样才能造出受欢迎的轮子╮( ̄▽ ̄)╭

声明:本站所有文章均为原创或翻译,遵循署名-非商业性使用-禁止演绎 4.0 国际许可协议,如需转载请确保您对该协议有足够了解,并附上作者名(Est)及原贴地址