Retrofit 源码阅读笔记(四)
第一篇文章中介绍了 Retrofit
的动态代理实现、方法注解解析等等内容:Android Retrofit 源码阅读笔记(一)。
第二篇文章中介绍了 Retrofit
是如何解析方法中的参数的信息:Android Retrofit 源码阅读笔记(二)。
第三篇文章中介绍了 Retrofit
是如何构建 Http
请求任务:Android Retrofit 源码阅读笔记(三)。
本篇文章是系列文章的第四篇,讲道理前面几篇文章已经把 Retrofit
的整个流程跑通了,后续应该没有什么讲的了才对,但是在 Retrofit
使用中还有两个高级用法,那就是自定义 CallAdapterFactory
和 ConverterFactory
,我就当读者已经读过我的前面几篇文章了,对这两个类也不再多解释,本篇文章就以 Retrofit
官方定义的 RxJava3CallAdapterFactory
和 MoshiConverterFactory
的源码分析来帮助大家更好的理解如何自定义一个 CallAdapterFactory
和 ConverterFactory
。整理好心情准备出发。
RxJava3CallAdapterFactory
这里默认大家都熟悉 RxJava
,不熟悉的同学自己去网上找一下资料学习一下啰,这里就不单独介绍了,创建 RxJava3CallAdapterFactory
的方法有三种:RxJava3CallAdapterFactory#create()
、RxJava3CallAdapterFactory#createSynchronous()
和 RxJava3CallAdapterFactory#createWithScheduler()
。
create()
创建OkHttp
异步请求的RxJava3CallAdapterFactory
,最终的请求是在OkHttp
的Dispatcher
线程池中。createSynchronous()
创建OkHttp
同步请求的RxJava3CallAdapterFactory
,最终请求线程由RxJava
确定。createWithScheduler()
创建OkHttp
同步请求的RxJava3CallAdapterFactory
,最终请求线程由传递的Scheduler
来确定。
在前面的文章中也有提到,Retrofit
会根据 CallAdatperFactory#get()
方法来获取能够使用的 CallAdapter
,而 CallAdatperFactory
主要的判断依据就是通过 adatperType
(returnType
)来判断当前的 CallAdapterFactory
是否支持这种类型,如果不支持就直接返回空,Retrofit
就会尝试从其他的 CallAdapterFactory
中继续去查找。如果支持就创建一个对应的 CallAdapter
返回。
猴,我们来看看今天第一个方法 RxJava3CallAdapterFactory#get()
的实现:
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
// 如果 `adapterType` 是 Completable,直接返回 RxJava3CallAdapter 对象
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.
// 如果是 Completable 它的 `responseType` 直接指定为 Void,也就是 Completable 不需要返回值。
return new RxJava3CallAdapter(
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;
// 如果 `adatperType` 不是 Flowable,Single,Maybe,Observable 其中之一,直接返回空,表示当前的 adapterType,不能处理直接返回空
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
// adapterType 中必须有详细的泛型信息,否者报错。
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
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
// 获取泛型信息的 Class 对象
Class<?> rawObservableType = getRawType(observableType);
// 判断泛型类型是否是 Response
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException(
"Response must be parameterized" + " as Response<Foo> or Response<? extends Foo>");
}
// Response 的泛型对象为 responseType
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>");
}
// Result 对象的泛型类型为 responseType
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
// 其他情况,adapterType 的泛型就是 responseType
responseType = observableType;
isBody = true;
}
// 构建 RxJava3CallAdapter 对象返回。
return new RxJava3CallAdapter(
responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);
}
首先 RxJava3CallAdatperFactory
能够处理的 adapterType
是 Complateable
,Single
,Maybe
,Observable
和 Flowable
。
这里在简单介绍一下上面的代码:
- 如果
adapterType
是Complateable
,直接构建一个responseType
为Void
的RxJava3CallAdapter
返回。 - 如果
adapterType
不是Single
,Maybe
,Observable
和Flowable
中的之一,直接返回空,表示当前的adapterType
无法处理。 - 判断
adapterType
中的泛型的Class
对象:
-
Response
我们在讲协程的时候讲过,这就表示返回值需要Response
(Retrofit
),Response
的泛型类型就是responseType
。 -
Result
Result
对象是RxJava3CallAdatperFactory
中定义的,他会封装成功和失败的请求,通常出现请求错误就会抛出异常,通过Result
封装后就不会抛出异常了,成功和异常都会被封装在Result
对象中,我以前都还自己实现这样的功能,没想到有现成可以用的。Result
的泛型也是responseType
。 - 其他情况
其他请求就是adapterType
的泛型对象就是responseType
,这也是我们开发中用到最多的情况。
- 构建
RxJava3CallAdapter
对象。
RxJava3CallAdapter
在前面的文章中我们知道了 CallAdapter
的主要职责就是通过 adapt()
方法创建 adapterType
的对象实例,然后返回给被代理的方法。我们来看看 RxJava3CallAdapter#adapt()
方法的实现:
@Override
public Object adapt(Call<R> call) {
// 根据同步调用和异步调用构建最基础的 Observable 对象,该流处理的对象是 Response
Observable<Response<R>> responseObservable =
isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call);
Observable<?> observable;
// 判断需要的流处理对象的类型,然后在用其他的 Observable 对象封装。
if (isResult) {
// 如果需要 Result 对象,用 ResultObservable 对元素流再封装
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
// 如果需要普通 Body,用 BodyObservable 封装
observable = new BodyObservable<>(responseObservable);
} else {
// 如果是需要有 Response,就用基础的 Observable 对象就好了。
observable = responseObservable;
}
// 在 Observable 中添加 scheduler
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
// 将 Observable 转换成需要的流类型。
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return RxJavaPlugins.onAssembly(observable);
}
解释一下上面的代码:
- 首先根据是否是异步调用来构建基础的
Observable
,同步调用的实现类是CallExecuteObservable
(后面分析),异步调用的实现类是CallEnqueueObservable
(后面分析),参数中的Call
的实现类是我们上一篇文章中讲的OkHttpCall
。基础Observable
流的返回数据是Response<T>
。 - 判断外部需要的流数据类型,如果需要
Result
,就用BodyObservable
(后面分析) 对基础的Observable
再封装;如果需要普通Body
,用BodyObservable
对基础的Observable
再封装;如果是需要Response
,那么就和基础的Observable
返回的类型就是一样的,直接使用即可。 - 如果有
Scheduler
就对上一个步骤中的Oberverble
添加一个Scheduler
,主要针对同步调用,同步调用的线程就由Scheduler
指定。 - 最后将
Observable
转换成需要的RxJava
的流类型(如果不需要转换就直接返回Observable
),也就是Single
,Maybe
,Flowable
,Completable
之一。
CallExecuteObservable
首先要了解上面提到的 RxJava
流都是冷流,最后订阅的时候会调用 Observable#subscribeActual()
方法,在这个方法里会触发真正的 Http
任务。CallExecuteObservable
是同步执行的基础流,它的流返回的数据是 Response<T>
,我们直接看 CallExecuteObservable
的完整源码:
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) {
// Since Call is a one-shot type, clone it for each new observer.
// 复制 call,因为这个每次流的订阅都会触发新的请求任务,但是一个 Call 只能请求一次,所以这里要复制一个 Call。
Call<T> call = originalCall.clone();
// 添加一个 CallDisposable,用来监听流的状态,如果流中途被取消订阅,那么需要把 Call 也取消。
CallDisposable disposable = new CallDisposable(call);
observer.onSubscribe(disposable);
if (disposable.isDisposed()) {
return;
}
boolean terminated = false;
try {
// 直接同步执行 Http 请求任务。
Response<T> response = call.execute();
// 数据返回后检查流是否还存活然后执行 onNext() 和 onComplete() 方法。
if (!disposable.isDisposed()) {
observer.onNext(response);
}
if (!disposable.isDisposed()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposable.isDisposed()) {
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;
private volatile boolean disposed;
CallDisposable(Call<?> call) {
this.call = call;
}
@Override
public void dispose() {
// 如果流取消,把 Call 的任务也取消了。
disposed = true;
call.cancel();
}
@Override
public boolean isDisposed() {
return disposed;
}
}
}
对 subscribeActual()
方法简单总结下:
- 复制
call
,因为这个每次流的订阅都会触发新的请求任务(也就是所谓的冷流),但是一个Call
只能请求一次,所以这里要复制一个Call
。 - 添加
CallDisposable
来监听流的状态,如果流已经取消了,把Call
的任务也取消。 - 直接调用
Call#execute()
方法同步请求,完成后检查流的状态,然后调用Observer
的onNext()
和onComplete()
方法,如果这个过程中有错就调用onError()
方法。
CallEnqueueObservable
CallEnqueueObservable
是异步调用的基础 Observable
,它的流返回的数据格式也是 Response<T>
,我们看看它的源码:
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallEnqueueObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override
protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
// 构建 CallBallback 对象来监听 Observer 的订阅状态和监听 Http 请求的异步调用
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
if (!callback.isDisposed()) {
// 异步请求
call.enqueue(callback);
}
}
private static final class CallCallback<T> implements Disposable, Callback<T> {
private final Call<?> call;
private final Observer<? super Response<T>> observer;
private volatile boolean disposed;
boolean terminated = false;
CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
this.call = call;
this.observer = observer;
}
@Override
public void onResponse(Call<T> call, Response<T> response) {
// 请求成功,如果流已经取消就直接返回
if (disposed) return;
// 执行 Observer 的 onNext() 和 onComplete() 方法
try {
observer.onNext(response);
if (!disposed) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposed) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
@Override
public void onFailure(Call<T> call, Throwable t) {
if (call.isCanceled()) return;
// 请求失败,调用 Observer 的 onError() 方法
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
@Override
public void dispose() {
// 任务取消。
disposed = true;
call.cancel();
}
@Override
public boolean isDisposed() {
return disposed;
}
}
}
上面的方法很简单,在执行订阅的 subscribeActual()
方法中执行 Call#enqueue()
方法异步调用 Http
任务,监听请求的回调用的是 CallCallback
对象,它也是监听流取消的对象。
在 CallCallback#onResponse()
的回调中表示请求成功, 如果流没有取消的情况下,依此调用 Observer
的 onNext()
与 onComplete()
方法,如果在这个过程中出错就调用 onError()
方法。
子啊 CallCallback#onFailure()
的回调中表示请求失败,直接调用 Observer
的 onError()
方法。
ResultObservable
ResultObservable
是将基础的返回 Response<T>
的 Observable
流转换成返回 Result<T>
的流,它永远不会触发 onError()
,成功和失败都会被封装在 Result
对象中,我们来看看它的实现:
final class ResultObservable<T> extends Observable<Result<T>> {
private final Observable<Response<T>> upstream;
ResultObservable(Observable<Response<T>> upstream) {
this.upstream = upstream;
}
@Override
protected void subscribeActual(Observer<? super Result<T>> observer) {
// 将上层流传过来的数据用 ResultObserver 对象来监听
upstream.subscribe(new ResultObserver<>(observer));
}
private static class ResultObserver<R> implements Observer<Response<R>> {
private final Observer<? super Result<R>> observer;
ResultObserver(Observer<? super Result<R>> observer) {
this.observer = observer;
}
@Override
public void onSubscribe(Disposable disposable) {
observer.onSubscribe(disposable);
}
@Override
public void onNext(Response<R> response) {
// 请求成功,把 Response 用 Result 封装,然后调用 `Observer#onNext()` 方法传递给下游。
observer.onNext(Result.response(response));
}
@Override
public void onError(Throwable throwable) {
// 请求异常,把 `Throwable` 用 Result 封装,然后调用 `Observer#onNext()` 方法传递给下游
try {
observer.onNext(Result.error(throwable));
} catch (Throwable t) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
return;
}
observer.onComplete();
}
@Override
public void onComplete() {
observer.onComplete();
}
}
}
在 subscribeActual()
方法中将上层流传过来的数据用 ResultObserver
对象来监听,在 ResultObserver#onNext()
方法中表示请求成功,把 Response<T>
用 Result<T>
封装,通过 Observer#onNext()
方法传递给下游的 Observer
;在 ResultObserver#onError()
方法中表示请求失败,把 Throwable
对象用 Result<T>
方法封装,同样通过 Observer#onNext()
方法传递给下游的 Observer
。
BodyObservable
BodyObservable
它的工作只是简单的将基础 Observerable
流中的 Response<T>
中的数据转换成 ResponseBody
,它的工作方式和 ResultObservable
类似,只是不拦截异常的信息:
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<>(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()) {
// 成功直接取 ResponseBody 传递到下游去。
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 {
// This should never happen! onNext handles and forwards errors automatically.
Throwable broken =
new AssertionError(
"This should never happen! Report as a bug with the full stacktrace.");
//noinspection UnnecessaryInitCause Two-arg AssertionError constructor is 1.7+ only.
broken.initCause(throwable);
RxJavaPlugins.onError(broken);
}
}
}
}
上面的代码和 ResultObservable
非常类似,就没有太多要说的了。
MoshiConverterFactory
如果大家不熟悉 Moshi
的同学,可以去了解一下,如果使用 Kotlin
开发,Moshi
相对于年老体衰的 Gson
还是有很多优势的,推荐还在使用 Gson
的同学迁移到 Moshi
。
MoshiConverterFactory
的实例创建是通过 MoshiConverterFactory#create()
方法创建,可以传入自定义的 Moshi
对象,如果没有传入,MoshiConverterFactory
会帮你创建一个默认的。
我们来看看 Converter.Factory
这个抽象类的重要的方法:
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;
}
// ...
}
responseBodyConverter()
构建请求任务时需要通过该方法获取将ResponseBody
转换成目标对象的Converter
。请求成功后就直接用Converter
来转换。requestBodyConverter()
构建请求时,需要通过该方法获取将目标对象转换成RequestBody
的Converter
(有@Body
/@Part
时 才会去获取),需要转换时直接用Converter
转换。stringConverter()
获取将其他的对象转换成String
对象的Converter
,例如在构建请求时,@Query
注解修饰的参数就需要转换成String
对象,就会用到该方法获取对应的Converter
。
MoshiConverterFactory
实现了 responseBodyConverter()
和 requestBodyConverter()
方法,也就是说它不支持由其他对象转换成 String
。
MoshiRequestBodyConverter
先来看看 MoshiConverterFactory#requestBodyConverter()
方法的实现:
@Override
public Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
// 根据输入的 Type 获取 Moshi 的 JsonAdapter
JsonAdapter<?> adapter = moshi.adapter(type, jsonAnnotations(parameterAnnotations));
// 更新 JsonAdapter的 配置
if (lenient) {
adapter = adapter.lenient();
}
if (failOnUnknown) {
adapter = adapter.failOnUnknown();
}
if (serializeNulls) {
adapter = adapter.serializeNulls();
}
// 创建 Converter 对象。
return new MoshiRequestBodyConverter<>(adapter);
}
这里简单说一下 Converter
它的第一个范型表示输入的类型,第二个参数表示转换后的类型,转换通过 convert()
方法。然后看看上面的代码:
- 通过输入的类型获取
Moshi
中的JsonAdatper
对象,序列化/反序列化都是依靠这个对象。 - 更新
JsonAdatper
的配置。 - 创建
MoshiRequestBodyConverter
对象返回方法。
我们再看看 MoshiRequestBodyConverter#convert()
方法具体是如何转换的:
@Override
public RequestBody convert(T value) throws IOException {
// 创建 OkIo 的 Buffer 对象.
Buffer buffer = new Buffer();
// 以 Buffer 为参数创建一个 JsonWriter 对象。
JsonWriter writer = JsonWriter.of(buffer);
// 将转换后的对象写入到 Buffer 中。
adapter.toJson(writer, value);
// 构建类型为 `application/json; charset=UTF-8` 的 RequestBody
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
上面代码很简单:
- 首先构建一个
OkIo
的Buffer
对象,然后由Buffer
对象再创建一个JsonWriter
对象。 - 通过
JsonAdapter#toJson()
方法将序列化后的数据写入到Buffer
中。 - 将
Buffer
中的数据转换成String
,然后构建一个类型为application/json; charset=UTF-8
的RequestBody
。
MoshiResponseBodyConverter
再来看看 MoshiConverterFactory#responseBodyConverter()
方法的实现:
@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);
}
几乎和 requestBodyConverter
用同样的方式构建了一个 JsonAdapter
,然后返回了 MoshiResponseBodyConverter
对象。
我们再看看 MoshiResponseBodyConverter#convert()
方法的实现:
@Override
public T convert(ResponseBody value) throws IOException {
// 获取 ResponseBody 中的 Source(OkIo) 对象。
BufferedSource source = value.source();
try {
// Moshi has no document-level API so the responsibility of BOM skipping falls to whatever
// is delegating to it. Since it's a UTF-8-only library as well we only honor the UTF-8 BOM.
// 判断开头的 3 个字节是否是 `0xEFBBBF`,如果是就跳过这几个字节
if (source.rangeEquals(0, UTF8_BOM)) {
source.skip(UTF8_BOM.size());
}
// 构建 JsonReader 对象
JsonReader reader = JsonReader.of(source);
// 读取 JsonReader 中的数据,然后反序列化为目标对象。
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();
}
}
简单总结一下上面的代码:
- 获取
ResponseBody
中的Source
(OkIo
) 对象。 - 判断
Source
对象中的前 3 个字节是否是0xEFBBBF
,如果是就跳过。 - 通过
Source
来构建JsonReader
(Moshi
) 对象。 - 通过
JsonAdatper#fromJson()
方法读取JsonReader
中的数据,然后反序列化为目标对象。 - 检查
JsonReader
中的Json
是否正确读取完毕,最后返回反序列化的对象。
总结
今天以 Retrofit
官方实现的 RxJava3CallAdapterFactory
和 MoshiConverterFactory
源码分析让大家了解如何自定义一个优秀的 CallAdapterFactory
和 ConverterFactory
,如果大家自己对别的 CallAdapterFactory
或者 ConverterFactory
感兴趣,自己也可以去看看他们的实现。
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。