四.源码解析
读源码如何开始呢?
我们先带着问题看源码,Retrofit有几个关键的流程
- Retrofit 如何将定义的interface转换成网络请求?
- Retrofit的Converter机制是如何实现?
- Retrofit的CallAdapter机制是如何实现?
1. 寻找入口
一行一行读,肯定是不可行的,太累了,而且脑容量不够,记不住,合适的读源码方式是从程序入口开始入手。当前功能开始读。
当前请求的入口发生在enqueue, 那么,我们就开始从这个Api入手读源码.
enqueue, 是进入队列的意思,进去查看,竟然是个
void enqueue(Callback<T> callback);
如果出现类似抽象方法;就得往回看了,因为读不下去了
2. 寻找接口实现
所以我们往上面找,上面的Api是 enqueue,去找 相关接口实现,找了半天,爱哭,接口实现是GithubService
public interface GitHubService { @GET("users/{user}/repos") Call<List<MicroKibacoRepo>> listRepos(@Path("user") String user); }
而GithubService.java是我自己创建的,怎么办呢? 继续往回看,找呀找, 找到了Retrofit的初始化方法 create,整个源码我就不翻出来了,翻一翻关键的部分,其中需要讲述的APi有:
- eagerlyValidateMethods
- newProxyInstance
- Platform
- invoke
- invokeDefaultMethod
public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(service); } return (T) // --------动态代理-------- Proxy.newProxyInstance( // 提供动态类的实例 service.getClassLoader(), // 获取 GithubService 的实例,获取需要动态代理类的接口,在 retrofit.create 传入 new Class<?>[] { service }, // new InvocationHandler() { // 判断接口平台,是JDK 7.0/8.0 或者 Android/IOS private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object[0]; @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // 如果这个方法不是直接声明的,那么就直接调用了,兼容性,保护性,不至于越权 if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } // java 8 开始,接口运行有默认的方法实现了 if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); } static <T> void validateServiceInterface(Class<T> service) { // 1. 验证 GitHubService 是否为一个接口 if (!service.isInterface()) { throw new IllegalArgumentException("API declarations must be interfaces."); } // 2.验证 GitHubService 是否继承其他接口,只接受原生接口 if (service.getInterfaces().length > 0) { throw new IllegalArgumentException("API interfaces must not extend other interfaces."); } } // 3. 在被初始化的时候,是有一个初始化过程,会去读注解,中间是有耗时的,分布式加载网络请求, validateEagerly 是方便调试的 private void eagerlyValidateMethods(Class<?> service) { Platform platform = Platform.get(); for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method)) { loadServiceMethod(method); } } }
Platform.java 看一下相关实现,里面包含两个平台一个是 Java8 还有一个 Android,这个APi主要是平台标识,知道就行了,没什么好说的
private static Platform findPlatform() { try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { // Android 平台 return new Android(); } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional"); // Java8 平台 return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); }
loadServiceMethod 里面也没有 invoke,我们通过 parseAnnotations 去找 一下invoke试试看能否找到,
ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result; }
ServiceMethod.java里面,不过也是一个抽象方法 ,于是我们往回看 parseAnnotations,看里面是否有 invoke 的逻辑实现,找到了,好家伙,parseAnnotations是ServiceMethod子类HttpServiceMethod实现方法,而HttpServiceMethod一定有invoke实现
abstract class ServiceMethod<T> { static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError(method, "Service methods cannot return void."); } // 通过 parseAnnotations 去寻找 invoke实现 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract T invoke(Object[] args); }
不用说,我直接在HttpServiceMethod.java, ctr + f 搜,便搜到了invoke,原来底层真是通过OKHttp实现的:
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> { // ----为了避免浪费篇幅,省略若干无用代码---- @Override ReturnT invoke(Object[] args) { return callAdapter.adapt( new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)); } }
上面我说过,看到抽象方法,往回看 ,所以我们来看 okHttpCall,OKHttpCall实现了Call接口 ,重点说一下一下方法:
- createRawCall
// OKhttp3的Call帮助Retrofit实现网络请求的Call private okhttp3.Call createRawCall() throws IOException { okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
- call.enqueue
call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { // response 结果交给 Retrofit 使用 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(); } } }); }
什么是动态代理?
动态代理是创建一个对象,这个对象传入一个接口并且帮你实现每一个接口的每一个方法,并且这每一个接口的每一个方法都会指向每一个接口每一个方法的invoke方法。
- callAdapter
HttpServiceMethod.java里面的构造方法, 我们找到了 CallAdapter,然后去里面查看是通过 createCallAdapter返回的
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method) { Type returnType = method.getGenericReturnType(); Annotation[] annotations = method.getAnnotations(); try { // CallAdapter 创建 return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create call adapter for %s", returnType); } }
进入 Retrofit.java 查看一下:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null, returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { // 通过 callAdapterFactories 获取 callAdapter for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } // ----为了避免浪费篇幅,省略若干无用代码---- }
callAdaperFactory是通过 Retrofit 的 build 方法构建而来.
public Retrofit build() { converterFactories.addAll(this.converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
我们看到 callAdaperFactory 通过 addAll 一次性添加过来,所以有我们看一下defaultCallAdapterFactories方法.
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories( @Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor); return Build.VERSION.SDK_INT >= 24 ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory) : singletonList(executorFactory); }
然后我们再看一下 ExecutorCallAdapterFactory
五. 面试题分享
Retrofit请求参数说明
Retrofit中的设计模式
1. 建造者模式
Retrofit对象的创建、ServiceMethod对象创建都使用Build模式,将复杂对象的创建和表示分离,调用者不需要知道复杂的创建过程,使用Build的相关方法进行配置创建对象。
2. 外观模式
Retrofit对外提供了统一的调度,屏蔽了内部的实现,使得使用该网络库简单便捷。 门面模式: 提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口。使用子系统更容易使用
3. 动态代理模式
通过动态代理的方式,当调用Retrofit的create()方法时,会进行动态代理监听。当执行具体的接口方法时,会回调InvocationHandler。通过反射解析method的标注及参数,生成ServiceMethod对象。
4. 静态代理模式
Android平台默认的适配器ExecutorCallbackCall,采用静态代理的模式。具体的实现delegate为OkHttpCall。
5. 工厂模式
Converter及CallAdapter的创建都采用了工厂模式进行创建。
6. 适配器模式
CallAdapter的adapt采用了适配器模式,使得interface的返回对象可以动态扩展,增强了灵活性
CallAdapter的种类
Converter种类
Retrofit支持多种数据解析方式,使用时需要在Gradle添加依赖。
Retrofit流程总结