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 使用教程(含实例讲解)