前言
本文是Retrofit2进阶系列的第一篇---从源码角度看Retrofit2实现原理,我会尽可能用简洁的代码帮大家理解Retrofit实现一次网络请求的核心流程是怎样的,这个流程整体上就4个步骤,是不复杂的,希望大家带着信心读下去,在文章末尾,我也为大家做出了简单的总结,希望能帮大家更好的理解这个框架,希望在读文章的你能有一些收获,能有更大的进步。备注:基于
Retrofit2.4.0
分析
系列文章:
Retrofit2进阶】---启示、思想
先来看一个最基础的网络请求案例:
//1、创建Retrofit接口
public interface ApiService {
@GET("/")
Observable<String> getData();
@GET("/")
Call<String> getData2();
}
//2、retrofit相关配置
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://xxxx/")
.client(client)
//json转换
.addConverterFactory(GsonConverterFactory.create())
//RxJava2转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
//创建接口对象
ApiService apiService = retrofit.create(ApiService.class);
//3、接口方法调用
3.1 call调用
apiService.getData2().enqueue();
3.2结合rxjava调用
apiService.getData().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
下面就来分析一下Retrofit2
是如何完成一次完整的网络请求的。
先来看一下Call调用
public interface ApiService {
@GET("/")
Call<String> getData2();
}
通过接口调用会返回一个Call
对象,如果你看过OkHttp源码的话,应该会对这个Call
很熟悉,它封装了一个网络请求的任务,但是它却不做网络请求,而是通过调用enqueue()
或者execute()
来发起真正的网络请求。
那这个Call
对象如何生成的?其实可以在retrofit.create()
方法中找到答案。
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 the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
create()
内部的核心就一件事情,通过动态代理生成一个代理类对象,具体来说就是通过Proxy.newProxyInstance()
来创建的。然后在回调方法invoke()
内部通过一系列解析,包装,最终返回用于发起网络请求的Call
对象或者用于结合rxjava
使用的Observable
对象。
这里的关键点与难点在于,你要懂代理模式和动态代理,如果你还不会的话,建议先简单学习一下再接着往下看,不然很多逻辑的连贯性你是不懂的。这里推荐一下我之前的一篇文章Java动态代理那些你容易忽略的细节。
先说一下Retrofit2动态代理的逻辑
//retrofit的API接口对象
ApiService apiService;
//创建代理对象
apiService = retrofit.create(ApiService.class);
//调用代理类中的方法
apiService.xxx();
首先生成一个代理类对象,当调用代理类的方法时,会回调执行InvocationHandler
的invoke()
方法
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
//省略,不会执行的代码
//生成Call关键在这里
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
-
ServiceMethod
是对接口中的方法进行解析,包括注解、参数,生成Http Request,具体来说是toRequest()
,将response转换为String或者实体类,具体说是toResponse()
; -
OkHttpCall
是对okhttp3.call的封装,以及okhttp3的其他方法的调用; -
serviceMethod.callAdapter.adapt(okHttpCall);
通过calladapter转换器,将 okhttp3.call转换成可以用于发起网络请求的retrofit2.Call
或者说用于rxjava的Observable
下面对ServiceMethod
、 OkHttpCall
、CallAdapter
做一个简单的解释,注意不是详解,这样可以让你避免陷入一叶障目的困境。我们先搞清楚主流程,那些细枝末节后面再看呗。
1、ServiceMethod
它是通过建造者模式来创建的,核心内容如下:
这部分内容先不用详细理解,可以先看个大概,后面再单独来看
public ServiceMethod build() {
//获取具体的网络适配器对象CallAdapter,如果retrofit配置了rxjava2转换器,那这里就是RxJava2CallAdapter
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
//获取响应转换器
responseConverter = createResponseConverter();
//解析方法注解,比如@GET、@POST、@FormUrlEncoded等等
//这里解析完毕之后可以获取到Http请求方式,请求体,url等信息
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//解析当前方法的参数
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
}
2、OkHttpCall
它继承于Retrofit2.Call
,内部就是对okhttp3
一系列操作的封装,甚至说代码都是直接copy的。这里就不展开详细解释了。注意:不要被OkHttpCall
的名字所迷惑,它不是okhttp3
中的call
,而是Retrofit2.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; // Either a RuntimeException or IOException.
@GuardedBy("this")
private boolean executed;
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
3、callAdapter
上面invoke()
方法中,最后一步是return serviceMethod.callAdapter.adapt(okHttpCall);
,
上面有提到过,这一步的作用是返回一个Retrofit2.Call
或者Observable
。
这里的CallAdapter
对象是一个接口对象,所以需要找到他的实现类。先回顾一下在Retrofit
配置的时候,有这么一行代码.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
,它可以将接口方法返回Observable
,如果不加这个配置,会如何呢?答案是会返回Retrofit2.Call
类型,具体是如何产生的,请看如下流程:
retrofit.build()---->platform.defaultCallAdapterFactory()--->Platform.ExecutorCallAdapterFactory--->ExecutorCallAdapterFactory.ExecutorCallbackCall
3.1 Retrofit没有配置callAdapter时
serviceMethod.callAdapter
就是ExecutorCallAdapterFactory.get()
返回的CallAdapter
实例,然后调用它的adapt
会返回一个ExecutorCallbackCall
对象。简单看一下这个对象,它是继承于Call
的。
static final class ExecutorCallbackCall<T> implements Call<T> {
3.2 Retrofit配置了RxJava2CallAdapterFactory时
serviceMethod.callAdapter
就是RxJava2CallAdapter
,调用它的adapt
会返回一个Observable
对象。
到这里就搞清楚了生成Retrofit2.Call
或者Observable
的整个流程,最后就只剩下一步了,发起网络请求和响应是如何实现的。
4、网络请求的实现
4.1 Call实现网络请求
上面提到过Call
对象是通过enqueue()
或者execute()
发起网络请求的,而这个Call
对象实际上是ExecutorCallbackCall
的实例
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
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);
}
});
}
});
}
所以,当我们外部调用enqueue()
时,实际调用的就是ExecutorCallbackCall.enqueue()
,而这里的delegate
是OkHttpCall
,所以最终会由OkHttpCall
内部的okhttp3
去执行。
这里还有一个关键点callbackExecutor
,它的来源如下:
//Platform.MainThreadExecutor.java
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
可以看到enqueue
的回调结果是在主线程中。
4.2 Observable实现网络请求
从之前的分析中,我们可以知道Observable
是在RxJava2CallAdapter
内部的adapt()
方法返回的:
@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;
}
//这里为null
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
//可以转换成Flowable
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
关键点在第一行代码,isAsync
返回true,所以看一下CallEnqueueObservable
的实现
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();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
call.enqueue(callback);
}
如果你看过RxJava2的源码的话,应该对这段代码非常熟悉,每个Observable
都会去调用subscribeActual()
方法。这里通过call.enqueue()
去发起网络请求,然后通过CallCallback
回调
private static final class CallCallback<T> implements Disposable, Callback<T> {
private final Call<?> call;
private final Observer<? super Response<T>> observer;
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 (call.isCanceled()) return;
try {
observer.onNext(response);
if (!call.isCanceled()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable 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));
}
}
}
}
@Override public void onFailure(Call<T> call, Throwable t) {
if (call.isCanceled()) return;
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
@Override public void dispose() {
call.cancel();
}
@Override public boolean isDisposed() {
return call.isCanceled();
}
}
}
这里的逻辑也很简单,就是把网络请求的结果发射出去。
到这里,Retrofit2
网络执行流程的源码分析就算完了。其实这里的类不算多,逻辑上也比较清晰,但是需要掌握的知识点比较杂,比如入口处的动态代理,中间的OkHttp、RxJava2源码。所以,这里建议基础薄弱的同学,看完这些内容之后再回头来看Retrofit2
,理解会更加深刻。
总结
流程
1、通过建造者模式创建一个Retrofit实例,也就是做Retrofit相关配置;
2、通过Retrofit对象的creat()
方法创建一个代理对象,当调用接口方法时,都会调用动态代理的invoke()
方法;
3、invoke()
内部做了3件事情:
- 3.1 会对method进行解析,最后生成
ServiceMethod
对象,并缓存起来,下次调用就不需要解析了; - 3.2 将原始的
okhttp3.call
封装成OkHttpCall
- 3.3 通过
CallAdapter
转换成Call
对象或者Observable
对象
4、如果返回Call对象,调用execute
或者enqueue
方法去做网络请求;如果返回Observable
对象,则结合rxjava2做后续的操作。
结论:
Retrofit是一个封装了网络请求的框架,它本身是不做网络请求的,而是通过
Okhttp
实现的;Retrofit提供了一种更简洁的发起网络请求的方式,具体来说是通过接口和注解的方式来简化网络请求相关的一系列配置;
可扩展性。比如说Client、数据转换Gson、RxJava适配等。
推荐文章:
Retrofit分析-经典设计模式案例