17年就打算好好读下Retrofit
的源码的,后来由于种种原因耽搁了,现在终于有时间来写博客记录下自己读源码的总结了。Retrofit
是一套网络请求封装库,底层网络请求还是OkHttp
,它只是让请求的方式变成接口的描述方式,源码虽然不多,但是是设计模式的典范,里面结合各种设计模式,以及许多优秀的设计思想,非常值得阅读的。
一、环境
Retrofit下载地址,它是用Maven
构建的,至于工具,我用Idea工具看的,可以自行去官网下载最新版本查看。导入之后的目录结构是这样的
只需要看Retrofit
这个Model
,其它是Retrofit
的扩展。
二、源码执行流程
首先还是从它的调用流程开始看,我们进行网络请求第一步还是创建Retrofit对象,一般创建过程如下:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL) //BASE_URL为请求的基地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器为GSON
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //将返回的Response适配到RxJava平台
.build();
可以看到Retrofit
的创建是通过Build
构建者模式创建,一般会为它设置BASE_URL
,ConverterFactory
,CallAdapterFactory
,我们点进去看的build()
方法,
public Retrofit build() {
if (baseUrl == null) { //从这里可以看到baseUrl是必须设置的,不设置就会抛异常
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient(); //这里的callFactory不设置默认为OkHttpClient,callFactory也就是你真正发请求的工厂类
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor(); //里面封装的是Handler,用它来做异步切换的
}
//设置的CallAdapterFactory添加到List集合中,第一步会添加我们设置的,后面才会添加一个默认的defaultCallAdapterFactory。
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
//设置的ConverterFactory添加到List集合中,第一步会添加一个默认的BuiltInConverters,后面才会添加我们设置的。
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
//创建我们的retrofit对象
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
在看这段代码时候里面会有一个Platform
,它是一个平台类,通过实现它,用来适配不同平台。
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android(); //从这里可以看出默认的平台就是Android平台
}
} catch (ClassNotFoundException ignored) {
}
}
... //省略部分代码
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
}
从这段代码中可以看出Platform
可以适配不同平台,默认给我们适配的平台就是Android
,我们前面调用platform
的方法都是调用它的Android
子类里面的方法。看下它里面的方法
defaultCallbackExecutor()
方法里面就是持有MainThreadExecutor
的实例对象,而MainThreadExecutor
里面封装了一个Handler
,它通过Looper.getMainLooper()
让其运行在主线程,由于它的权限级别是私有的,它通过调用execute()
方法来进行线程切换。
defaultCallAdapterFactory()
就是默认的CallAdapterFactory
刚刚在CallAdapterFactories
集合里面添加的就是这个,这个很重要待会要用到,需要看里面的实现
到了这一步Retrofit
的创建就完成了。下一步就是传入接口方法获取其实例对象
//Github就是你在项目中的接口,里面是所有网络请求的接口描述
GitHub github = retrofit.create(GitHub.class);
我们点进去看create()
方法
public <T> T create(final Class<T> 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 {
... //省略部分代码
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
里面是用了动态代理
设计模式,返回的对象只是其代理对象。所有我们调用接口对象的方法都会走这段代码。逐行看代码
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
首先调用loadServiceMethod()
方法,通过它获取一个ServiceMethod
实例,这个实例封装了网络接口方法的描述,首先看loadServiceMethod
的实现
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;
}
ServiceMethod
是缓存到了一个Map
中,首先会通过Map
获取其实例,如果Map
中有其实例,就直接返回,否者创建一个缓存到Map
中,然后返回。
ServiceMethod
的创建也是通过构建者模式,看下build()
实现
public ServiceMethod build() {
callAdapter = createCallAdapter(); //创建callAdapter
...
responseConverter = createResponseConverter();
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];
...
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
可以看出ServiceMethod
的build()
方法里面主要做的事情是callAdapter
, responseConverter
实例的获取,以及解析方法注解,我们来看下callAdapter
的实例是怎么获取的
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
...
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);
}
}
可以看出还是要调用retrofit
的callAdapter
方法
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
...
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
代码片段省略了部分,最后还是会走到nextCallAdapter
方法去获取其实例,callAdapter
实例会从adapterFactories
获取,由于获取的是一个工厂类还是要调用一个get
方法从工厂获取其callAdapter
对象。adapterFactories
就是我们获取Retrofit
实例时候传入的,可以自定义,也可以用别人提供的,先设置的满足条件,先会被使用。
responseConverter
也是一样的方法去获取其实例。
这部分完了,再回到代理方法里,接着创建了一个OkHttpCall
实例
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
接着调用这句
serviceMethod.callAdapter.adapt(okHttpCall);
callAdapter
是获取retrofit
实例设置的,如果我们没用RxJava
,接口方法的返回值为Call
,那么这个callAdapter
获取的实例是这个
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
这个刚才说了,也就是Platform
的子类Android
,也就是ExecutorCallAdapterFactory
,也就是说最后会调用其adapt
方法
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
static final class ExecutorCallbackCall<T> implements Call<T> {
...
@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);
}
});
}
});
}
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
adapt
是返回一个ExecutorCallbackCall
的实例,它是call
的子类,然后我们会调用enqueue
去做网络请求,它是异步的,或者调用execute
做网络请求,它是同步的。在调用的时候,里面都是走的是delegate
代理类,也就是OkHttpCall
(OkHttpCall
后面再单独看)里面的方法,里面还是通过OkHttp
发送的网络请求,请求成功或者失败会回调okHttp
的回调,由于它的回调是异步的,接着调用callbackExecutor.execute
将线程从子线程切换到主线程,然后调用callback.onResponse
或者callback.onFailure
做回调,也就是我们常用Retrofit
发网络请求的回调。这时候代码也就是运行到了主线程。
三、总结
代码到了这里,一次完整的网络请求也就完毕了,这只是流程的讲解,详细代码细节后面再单独介绍。
推荐参看:
1、Android:手把手带你深入剖析 Retrofit 2.0 源码
2、 这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)