Retrofit源码解析
Retrofit内部如何实现接口调用
我们都知道Retrofit 是通过定义接口,然后拿到接口的实例并且调用对应的方法。我们就从使用流程开始看源码里是如何实现的。
1、首先通过 retrofit.create 方法拿到自定义的 service实例,上源码:
这里可以看到,通过动态代理的方式生成了自定义service 的对象。并且在调用自定义接口方法时 是执行了 1 处的方法。那么来看看loadServiceMethod 方法:
可以看到是在①处生出了一个ServiceMethod 对象兵返回,那么一步步看进去:
HttpServiceMethod.parseAnnotations:
这里返回了一个HttpServiceMethod 对象,所以动态代理里调用的其实就是HttpServiceMethod#invoke 方法,源码如下:
而OkHttpCall 则是对OkHttp的封装,调用接口的细节都在里面实现了,可以看下里面的enqueue 方法:
@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) {
throwIfFatal(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();
}
}
});
}
当然,从上面我们可以看到呢 HttpServiceMethod#invoke 方法中只是把OkHttpCall 当做参数传给了 callAdapter.adapt 方法,所以真正的调用接口的时机其实是在这里面。
总结:当service 里面的接口方法时,实际是调用HttpServiceMethod.invoke 方法。
请求的类型的判断
那么调用的流程我们搞清楚了,那么说说请求的类型是在什么时候判断的。其实是在 RequestFactory 创建的时候已经判断好了。
在ServiceMethod.parseAnnotations 方法中:
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
一步步点进去,最后会调用到RequestFactory.Builder.parseMethodAnnotation 方法:
可以看到这里就已经根据接口方法的注解来得到请求的类型了。
callAdapter 以及 responseConverter 的作用
其实呢有很多人可能都不明白这两个到底有什么作用,我们在初始化retrofit 的时候会有如下的代码:
图中的①②处就是分别添加了callAdapter 和 responseConverter 。
我就先简单说下他们的用处吧。我们定义接口的时候,可能有如下的代码:
那么这里的返回值是 Observable< TestStringResponse > ,其中的 Observable 是由callAdapter 来解析并且返回的,因为retrofit 默认的返回值是Call 。而尖括号里面的类型则是由responseConverter 根据responseBody 解析并返回的。
callAdapter可以理解成是返回值的适配器。
responseConverter 可以理解成是请求返回数据的转换器
1、callAdapter
那么来看看他说如何操作的。回到上面 HttpServiceMethod.parseAnnotations 方法:
这个方法里面①②处就分别根据调用的接口去获取了callAdapter 和 responseConverter。
①处代码如下:
returnType是定义的接口的返回类型,如我们上面举例的Observable< TestStringResponse > 。
annotations 是该接口的注解。
继续往下看 retrofit.callAdapter :
继续往下看nextResponseBodyConverter :
可以看到是遍历了converterFactories 这个集合,并调用集合元素中的get 方法来获取Converter 接口的实例。
converterFactories 这个呢就是适配器工厂的集合,里面的get方法是获取具体的适配器。
那么这个converterFactories 是这么来的呢?代码中可以看出,是在构造函数中赋值的,而构造函数则是在Builder.build 中调用的,如下:
①处的代码就新建了一个CallAdapter.Factory的集合,构造函数的参数 this.callAdapterFactories 就是我们创建Retrofit实例时调用 addCallAdapterFactory 加进来的适配器工厂。
可以看到适配器工厂里面是默认就有加入了一个工厂——platform.defaultCallAdapterFactories(callbackExecutor)。这个呢其实就是 DefaultCallAdapterFactory 的实例,我们看下他的源码:
responseType 方法呢后面会用到,这里先按下不表。
可以看到这个get方法里面限制了 ,只有返回值为 Call 类型的 才会返回有效的 适配器。而adapter方法中,则是将call 直接返回。
我们回顾一下adapt 方法是在哪里调用的? 是在调用我们定义的接口的时候,调用HttpServiceMethod.invoke 方法,而在该方法里面调用了callAdapter.adapt方法。
当我们添加了 rxjava 的callAdapter 时也是一样的,我们来看下RxJava2CallAdapterFactory.get方法:
@Override public @Nullable 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) {
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) {
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 {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
可以看到这里同样也会判断接口方法的返回值,只有满足条件的才会返回RxJava2CallAdapter 。
继续看下RxJava2CallAdapter.adapt方法:
可以看到用call对象生成了 CallExecuteObservable对象,该类继承自 Observable。并且在最后返回的是一个RxJavaPlugins.onAssembly(observable),这个方法里面的返回值就是Observable 类型的,所以这就实现了由默认的call类型转成返回的Observable类型。
我们继续看下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<T> call = originalCall.clone();
CallDisposable disposable = new CallDisposable(call);
observer.onSubscribe(disposable);
if (disposable.isDisposed()) {
return;
}
boolean terminated = false;
try {
Response<T> response = call.execute();
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() {
disposed = true;
call.cancel();
}
@Override public boolean isDisposed() {
return disposed;
}
}
}
subscribeActual 这个方法我不是很理解是什么时候调用的,看了下源码注释中的翻译:
操作符实现(包括源和中间)应该实现这个方法来执行必要的业务逻辑并处理传入的{@link Observer}。 不需要在当前的{@code Observable}实例或{@code Observer}上调用任何插件钩子; 在调用这个方法之前,{@link #subscribe(Observer)}已经应用了所有的钩子和基本的保护措施。
不是很理解,感觉应该是订阅的时候会调用这个方法(经过测试确实是订阅之后才会触发)。
在这个方法里面调用了call.execute() ,那么之前我们就知道这里的call 其实是OkHttpCall 类型的实例,那么我们看一下它里面execute的源码:
@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());
}
这里就是调用createRawCall 方法 创建了一个真正的请求,并且调用。
那么我们先总结一下:
当我们调用自定义的service里的接口方法时。retrofit会自动根据接口方法中定义的返回值去寻找对应的callAdapter。
然后调用callAdapter里面的adapt 方法将call类型转换为你想要的类型。
2、responseConverter
可能上面说 callAdapter 的时候有细心的同学留意到了。在CallExecuteObservable 类中,有这样一句:observer.onNext(response); 这里明明是将一个response 传到下游,但是我们平时实现订阅观察者的时候,是自定义类型的实体啊。那么我们就进一步来研究一下这个问题。
从上面我们就知道,我们在 OkHttpCall.execute 方法中呢就是返回了 parseResponse(call.execute()) 。其实这个parseResponse 方法就是将我们请求返回的body转换为我们定义的实体。我们看一下源码:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
其中有一句:T body = responseConverter.convert(catchingBody); 这里就是将返回的的body 转为我们定义的实体。
responseConverter 在HttpServiceMethod.parseAnnotations 方法中创建的。一步步传了进来:
注意这里①处,调用了callAdapter.responseType方法,我在前面的图里面特意标注了一句话:比如returnType 是 cal< Bean > 那么这里返回的就是Bean。没错这里获取到的就是我们接口方法返回值尖括号里面的类型。
我们看一下 GsonResponseBodyConverter 的源码:
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 {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
可以看到这里就是用gson 将 ResponseBody 转换为我们自定义的实体。
我们继续回到OkHttpCall 中。 parseResponse 方法中虽然是将responseBody 转成了自定义的实体,但是返回值还是 Response类型的,只不过是将Response.body 设置为我们的实体对象。所以在CallExecuteObservable.subscribeActual 方法中获取到的返回值是 Response 类型的。但是我们回到RxJava2CallAdapter.adapt 方法中:
注意①处的 isBody ,当isBody 为true 时 ,将 responseObservable 转化为BodyObservable。isBody变量是在RxJava2CallAdapterFactory.get 方法中传进来的:
也就是说我们自定义接口返回值的尖括号中的类型如果不是 Response 或者 Result 的子类的话,那么isBody = true。
我们回到BodyObservable 中,看看源码:
@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));
}
}
}
可以看到这里直接把 response.body() 传给下游,上面说过 response.body() 其实已经是我们设置过的 自定义的实体了。