Retrofit 源码解析
本文基于 Retrofit 2.5
Retrofit :改造
改造了什么呢?
把一个 Http 请求转化为一个 Java 接口的调用。
文章目录
- 一、简单使用
- 二、一次调用
- 2.1 InvocationHandler.invoke()
- 2.1.1 创建 ServiceMethod
- 2.1.1.1 创建 requestFactory
- 2.1.1.2 创建 callFactory
- 2.1.1.3 创建 callAdapter
- 2.1.1.4 创建 responseConverter
- 2.1.2 执行 ServiceMethod 的 invoke 方法
- 2.1.2.1 创建 OkHttpCall
- 2.1.2.2 callAdapter.adapt()
- 2.1.3 添加 GsonConverter
- 2.1.4 添加 RxJava2CallAdapter
- 三、整体流程
- 四、一些问题
- 五、借鉴学习
- 5.1 动态生成接口的实现类
- 5.2 工厂模式
一、简单使用
这是官网给的例子(http://square.github.io/retrofit/)。
定义 Service 接口,该接口内的方法就是 api 调用。
public interface GithubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user);}
创建 Retrofit 对象,并通过 Retrofit 对象再创建 Service 接口实现类的对象。
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build();GithubService githubService = retrofit.create(GithubService.class);
调用 Serice 对象的方法,发起网络请求。
Call<List<Repo>> repos = githubService.listRepos("gdeeer");
二、一次调用
从这句开始。
Call<List<Repo>> repos = githubService.listRepos("gdeeer");
点进去,发现找不到 listRepos 的实现。因为 githubService 的类是动态生成的,我们看不到类的实现。
只能去看下生成 githubService 对象的代码。
GithubService githubService = retrofit.create(GithubService.class);
2.1 InvocationHandler.invoke()
看 Retrofit 的 create() 方法。
public <T> T create(final Class<T> service) { ... return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { ... @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { ... return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } });}
可以看到,Retrofit 是通过 Proxy.newProxyInstance
来生成 GithubService 接口的实现类的,而接口内方法的处理逻辑就在 InvocationHandler 的 invoke() 中(更多关于Proxy.newProxyInstance
的内容可见Java 基础:静态代理和动态代理)。
invoke() 方法中执行了 loadServiceMethod(method).invoke(args)
。所以 githubService.listRepos("gdeeer");
方法的真正调用,就是在这里进行的。
2.1.1 创建 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 = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result;}
先从缓存中获取,缓存中没有,就通过 ServiceMethod.parseAnnotations()
来新建,并放入缓存。
abstract class ServiceMethod<T> { static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); ... return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract T invoke(Object[] args);}
ServiceMethod 是一个抽象类,只有一个方法 invoke(),ServiceMethod.parseAnnotations()
相当于一个工厂,用来创建 ServiceMethod 对象,它内部又调用了 HttpServiceMethod.parseAnnotations()
来创建。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method); ... Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);}
终于出现了 new HttpServiceMethod()
,HttpServiceMethod 是 ServiceMethod 的实现类,它接收4个参数:requestFactory、callFactory、callAdapter、responseConverter。
requestFactory
用来生成 okhttp3.Request,okhttp3.Request 代表一次 Http 请求。
callFactory
用来生成 okhttp3.Call,okhttp3.Call 代表一个准备好了的 Request。
callAdapter
用来处理 retrofit2.Call,retrofit2.Call 是 Retrofit 中定义的 Call,与 okhttp3.Call 基本一致,最终执行的还是 okhttp3.Call。
responseConverter
用来转化一个 response。
2.1.1.1 创建 requestFactory
ServiceMethod.parseAnnotations() 方法中会创建 requestFactory。
// ServiceMethod.javastatic <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); ...}// RequestFactory.javastatic RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build();}
通过 RequestFactory.Builder 来创建一个 RequestFactory。
2.1.1.2 创建 callFactory
HttpServiceMethod 的 parseAnnotations() 方法中会创建 callFactory。
创建方式是直接使用 Retrofit 类的 callFactory。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...) { okhttp3.Call.Factory callFactory = retrofit.callFactory; ...}
Retrofit 中的 callFactory 在 Retrofit.Builder.build()
时初始化。没有指定的话,默认就是一个 OkHttpClient
。
// Retrofit#Builder.javapublic Retrofit build() { ... okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } ...}
2.1.1.3 创建 callAdapter
HttpServiceMethod 的 parseAnnotations() 方法中会创建 callAdapter。
创建方式是通过 Retrofit 类,Retrofit 会遍历自己的 callAdapterFactories,找到合适的 CallAdaperFactory,如果找不到,会抛异常。
什么是合适的 CallAdaperFactory,就是能产生合适的 CallAdaper 的 Factory。什么是合适的 CallAdapter,就是能 Call 改编为指定的 returnType 的 CallAdapter。
CallAdapter
// HttpServiceMethod.javastatic <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...)(CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);...}private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(...) { ... return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); ...}// Retrofit.javapublic CallAdapter<?, ?> callAdapter(...) { return nextCallAdapter(null, returnType, annotations);}public CallAdapter<?, ?> nextCallAdapter(...) { ... int start = callAdapterFactories.indexOf(skipPast) + 1; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } ...}
Retrofit 中的 callAdapterFactories 在 Retrofit.Builder.build()
时初始化。
// Retrofit#Builder.javapublic Retrofit build() { ... Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); ...}
初始化时,根据所在的不同平台,会添加不同的默认工厂。
-
Android 平台上,callbackExecutor 是 MainThreadExecutor。若当前机器的 Android 版本号大于 24,会添加 CompletableFutureCallAdapterFactory、ExecutorCallAdapterFactory。若小于等于 24,只添加一个 ExecutorCallAdapterFactory。
-
Java8 平台上,callbackExecutor 是 null。会添加 CompletableFutureCallAdapterFactory、 DefaultCallAdapterFactory。
DefaultCallAdapterFactory 只能生产 DefaultCallAdapter,它将 Call 改编为 Call
(它自己)。
ExecutorCallAdapterFactory 只能生产 ExecutorCallAdapter,它将 Call 改编为 ExecutorCallbackCall
(也是一个 Call)。
CompletableFutureCallAdapterFactory 只能生产 CompletableFutureCallAdapter(实际上是 BodyCallAdapter、ResponseCallAdapter),它将 Call 改编为 CompletableFuture
。
2.1.1.4 创建 responseConverter
HttpServiceMethod 的 parseAnnotations() 方法中会创建 callAdapter。
创建方式是通过 Retrofit 类,Retrofit 会遍历自己的 converterFactories,找到合适的 ConverterFactory,如果找不到,会抛异常。
什么是合适的 ConverterFactory,就是能生产合适的 Converter 的 Factory。什么是合适的 Converter,就是能将 ResponseBody 转化为指定 returnType 的 Converter。
Converter
// HttpServiceMethod.javastatic <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...) { ... Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); ...}private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(...) { ... return retrofit.responseBodyConverter(responseType, annotations); ...}// Retrofit.javapublic <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) { return nextResponseBodyConverter(null, type, annotations);}public <T> Converter<ResponseBody, T> nextResponseBodyConverter(...) { ... int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { return (Converter<ResponseBody, T>) converter; } } ...}
Retrofit 中的 converterFactories 在 Retrofit.Builder.build()
时初始化。
// Retrofit#Builder.javapublic Retrofit build() { ... List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this.converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); ...}
初始化时,根据所在的不同平台,会添加不同的默认工厂。
-
Android 平台上,只会添加 BuiltInConverters。
-
Java8 平台上,会添加 BuiltInConverters、OptionalConverterFactory。
BuiltInConverters:
@Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter( Type type, Annotation[] annotations, Retrofit retrofit) { if (type == ResponseBody.class) { return Utils.isAnnotationPresent(annotations, Streaming.class) ? StreamingResponseBodyConverter.INSTANCE : BufferingResponseBodyConverter.INSTANCE; } if (type == Void.class) { return VoidResponseBodyConverter.INSTANCE; } if (checkForKotlinUnit) { try { if (type == Unit.class) { return UnitResponseBodyConverter.INSTANCE; } } catch (NoClassDefFoundError ignored) { checkForKotlinUnit = false; } } return null;}
它只能生产可以将 ResponseBody 转化为:ResponseBody
、Void
、Unit
的 Converter,如果指定的 returnType 不是这几种,就会返回 null。
OptionalConverterFactory:
@Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter( Type type, Annotation[] annotations, Retrofit retrofit) { if (getRawType(type) != Optional.class) { return null; } Type innerType = getParameterUpperBound(0, (ParameterizedType) type); Converter<ResponseBody, Object> delegate = retrofit.responseBodyConverter(innerType, annotations); return new OptionalConverter<>(delegate);}
它只能生产 OptionalConverter,它将 ResponseBody 转化为 Optional
,如果指定的 returnType 不是 Optional,就会返回 null。
2.1.2 执行 ServiceMethod 的 invoke 方法
2.1.2.1 创建 OkHttpCall
获取到 HttpServiceMethod 对象后,就会调用它的 invoke 方法。
@Override ReturnT invoke(Object[] args) { return callAdapter.adapt( new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));}
里面通过 requestFactory、callFactory、responseConverter 生成了一个 OkHttpCall
对象,CallAdapter 处理的就是它。
OkHttpCall 是 Retrofit2.Call 的实现类,它会包含一个 okhttp3.Call 的对象 rawCall,rawCall 通过 callFactory、requestFactory 创建。
okhttp3.Call rawCall = callFactory.newCall(requestFactory.create(args));
2.1.2.2 callAdapter.adapt()
接下来看 callAdapter 的 adapt() 方法。
adapt() 方法在 retrofit 包中,有四处实现。即包中定义了四个 CallAdapter,DefaultCallAdapter、ExecutorCallAdapter、BodyCallAdapter、ResponseCallAdapter。
DefaultCallAdapter
将 Call 改编为 Call。
ExecutorCallAdapter
将 Call 改编为 ExecutorCallbackCall(也是一个 Call)。
BodyCallAdapter
、ResponseCallAdapter
将 Call 改编为 CompletableFuture(Java8 中的类)。
我们再回头看下最开始的代码。
Call<List<Repo>> repos = githubService.listRepos("gdeeer");
实际运行后,发生了异常。
异常发生在 HttpServiceMethod.createResponseConverter() 方法中,即生产 Converter 的方法中。
如上面 2.1.1.4 中所说,生产 Converter 时,会遍历 Retrofit 中的 converterFactories,如果没有找到合适的 ConverterFactory,就会抛出异常。
默认的 converterFactories,只能生产 returnType 是 ResponseBody
、Void
、Unit
、Optional
的 converter。但我们的 listRepos() 方法的 returnType 是 Call
,所以它会返回 null。>
2.1.3 添加 GsonConverter
系统内置的 ConverterFactory 不满足需求,我们只能自己创建新的 ConverterFactory。
官方文档上说,Retrofit 默认只支持将 HTPP bodies 转为 ResponseBody。如果要支持其他类型,需要使用新的 Converter,并提供了几种 Converter 库。
我们使用 GsonConverter 来转化,引入 converter-gson 库后,修改 Retrofit 的 build 代码。
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build();
现在代码就可以正常运行了。
2.1.4 添加 RxJava2CallAdapter
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
RxJava2CallAdapter 将 Call 改编为一个 Observable。
Observable subscribe 时,会执行 Call,在 onNext 中回调。
三、整体流程
上面的目录已经很清楚,总结一下就是:
- 生成 ServiceMethod
- 调用 ServiceMethod.invoke
- 生成 CallAdapter、OkHttpCall
- 通过 CallAdapter 调用 OkHttpCall
四、一些问题
- 为什么 HttpServiceMethod 的四个构造参数中,requestFactory 是在 ServiceMethod.parseAnnotations 时生成,而其他参数是在 HttpServiceMethod.parseAnnotations 时生成?
应该是开发者觉得以后还有除了 HttpServiceMethod 以外的 ServiceMethod 实现类,但是他们都需要 requestFactory,所以放在调用 HttpServiceMethod.parseAnnotations 之前生成。
- 为什么 ServiceMethod 持有的对象,requestFactory、callFactory 使用的是 Factory,而 callAdatper、responseConverter 使用的 Factory 生产的产品?
因为 CallAdatper、ResponseConverter 对于每个方法来说,不管调用几次,它们的值都不变,但对于 Request、Call 来说,每次调用,都要产生不同的对象。
- 为什么 Retrofit 要新定义一个 retrofit2.Call,而不直接使用 okhttp3.Call?为什么没有一个 retrofit2.Request?
实现 retrofit2.Call 接口的有两个类,一个是代理了 okhttp3.Call 的 OkHttpCall
类,另一个是代理了另一个 retrofit2.Call
的 ExecutorCallbackCall 类。
ExecutorCallbackCall 会把 retrofit2.Call 的 execute()、enqueue() 方法都放到 Executor 中执行。
- RequestFactory、CallFactoty、CallAdapterFactory、ConverterFactory 都在哪里生成?他们的产品都在哪里生成(Factory 在哪里使用)?他们的产品在哪里使用?
RequestFactory 在 ServiceMethod.parseAnnotations
中生成。
Request 在 OkHttpCall.createRawCall 中生成并使用,用来生成 okhttp3.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;}
CallFactory 在 Retrofit.Builder.build() 方法中生成(即 OkHttpClient)。
Call 在 OkHttpCall.createRawCall 中生成并使用,用来生成 okhttp3.Call(会委托 OkHttpCall 调用它的方法)。OkHttpCall.createRawCall 在 OkHttpCall 执行方法时调用。
OkHttpCall 在 HttpServiceMethod.invoke 方法中生成。用户调用 api 方法后,获得 CallAdapter.adapt 生成的对象,再调用该对象的方法时使用。
CallAdapterFactory 在 Retrofit.Builder.build() 方法中生成。
CallAdapter 在 ServiceMethod.parseAnnotations
中生成,在用户调用 api 方法时使用。
ConverterFactory 在 Retrofit.Builder.build() 方法中生成。
Converter 在 ServiceMethod.parseAnnotations
中生成,在 OkHttpCall.execute
、OkHttpCall.enqueue
时使用。
五、借鉴学习
5.1 动态生成接口的实现类
5.2 工厂模式
更多相关文章
- Android(安卓)6.0关于权限的问题
- Android面试题(25)-Bundle机制
- Android中调用系统摄像并且保存到指定位置的一些问题&Uri转文件
- Android(安卓)Binder机制(3) 本地服务注册过程
- Android(安卓)程序获取、设置铃声音量
- 【Android(安卓)开发教程】理解Intent对象
- Parcelable使用(跨进程,Intent传输)
- Android(安卓)View,ViewGroup 事件分发
- GetSystemService的详解
随机推荐
- Android(安卓)Handler机制4之Looper与Han
- android 应用移植到ophone 平台需注意
- Android(安卓)JNI简单实例(android 调用C/
- 基于NDK的Android防破解& Android防破解
- 安卓textview edittext 中inputType的类
- Android中EditText的inputType属性(键盘类
- TextView过长显示省略号, TextView文字中
- Android(安卓)RelativeLayout 属性
- Android(安卓)JNI简单实例(android 调用C/
- listview android:cacheColorHint,androi