整体认识
Retrofit 用接口中的方法和注解来描述一个HTTP请求,用户只用关注接口如何描述这个请求,而不用关注内部的具体实现。它将网络请求中,封装Request 对象,解析Response对象等模板代码封装了起来,使得使用者只要描述做什么,而无需关心怎么做。
内部网络请求部分依赖了OkHttp,这样,解析方法后,就是OkHttp的工作了,创建Request,解析Response,而在这两个过程,涉及到 数据(json, xml, 二进制(protobuf))与Java对象的转换,即数据序列化/反序列,这里Retrofit没有新造轮子,而是提供一个适配器,让用户选择合适 自己需求的工具,完美践行了对扩展开放的原则。
动态代理
关于这个设计模式,说下自己的理解。
代理,需要一个服务ServiceA
,存在现有的类(代理目标类Obj
)可以满足或满足部分需求,这时,假设想让User
也拥有提供该服务的能力,
我们不是直接继承Obj
, 而时将该服务抽象为一个接口ProvideServiceA
,表示具备可以提供这个服务A,此时,真正提供具备这个服务实现类为Obj
,
而我们的User
也想拥有这份能力,可User
又不但仅有这份能力,它还可能拥有A,B,C能力,故,它在是实现了 ProviderServiceA
接口,但不是自己
实现,而是直接使用Obj
来提供该服务。
简单说,就是声明了具备某个服务的能力后,内部提供该接口的实现类的实例,在方法中转发该消息到实例来完成。
可以发现,当有一个类可以提供某个服务后,我们不是简单继承它来表示具备有该服务能力,而是添加一个接口,表示是是实现该接口的类都具备有这份能力,这样, 我们会发现,我们需要额外引入一个接口类,这是不是Java不支持多继承导致的额外成本呢?
这个问题我无法判断。
在Java的概念中,接口表示一份契约,只是表示提供了某个服务,具体的实现延迟到了具体的实现类实现。
一个复杂的类,可以实现多个接口,它表示可以提供一系列服务的类,这些服务对外形成了一个整体的概念,而在实现方法中,又可以划分为子服务,在内部使用
其他自服务的实例来完成,以这个概念来看,我觉得这样的思考方法非常符合分治
的思维,将大问题拆分为子问题,在子问题的实现上,可能又会继续拆分。
大问题和子问题之间的关系,完成依照它们的接口来完成,不会跟他们的子问题实现产生联系,这样,在查看代码时,使得我们很容易在了解这一个层次上类关系,
而不是陷入子问题实现的细节中。
好吧,扯得有点远了。
代理模式在印象中有一个案例是,在Android插件化中,对于Android四大组件类,我们会对他们进行插桩,在Manifest清单文件中
声明一个ProxyActivity,而在我们得插件类PluginActivity中,虽然我们实现了Activity得方法,但是其具体得实现是转发给ProxyActivity来是实现的,
比如 findViewById()
,getAssertManager()
方法,因为即使我们在插件模块中创建了Activity实例,我们也不能直接使用相关的方法,因为这个
Activity是没有在Android系统中注册,系统在处理Intent时是找不到该Activity。
而动态代理,区别于静态代理需要声明一个接口,在目标类和代理中都要是实现接口方法,动态代理不需要在编译时引入接口类,在调用代理类方法时,除了转发给 目标类对应方法,也可以添加自己的增强代码(日志、额外操作等)。
感叹细节实现
1 |
|
创建一个代理实例
1 | public <T> T create(final Class<T> service) { |
以下就是解析方法,执行方法了
解析方法
使用缓存避免解析多次
1 | ServiceMethod<?> loadServiceMethod(Method method) { |
解析出信息
1 | static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { |
HttpServiceMethod.java
解析注解信息后,依据返回值类型,选择可用的 CallAdapter、Converter
1 | static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( |
执行方法
在真正执行该方法时,跳到这里
1 | @Override |
比如在Rxjava中的 adapt方法实现
原本一个Call的返回只是一个Response,通过适配adapt,将其转换成我们想要的东西。
在RxJava中将Response创建了一个可以观察的源,
1 |
|
总结
整体下来,看得挺懵逼的~
基本思路,解析方法上的信息后,尤其时返回值类型,判断其需要的CallAdapter,用于将请求返回值构建成对应的实例。默认下,返回一个定义Call,表示了一个 请求,包括发送一个request和返回一个Response,当RxJava的适配器时则返回一个Observable。
另一个就是Converter,将对象转换成http协议支持的类型,比如Json,普通文本,或数据流。转换时,包括创建请求时的requestBodyConverter以及responseBodyConverter。
无论是CallAdapter,还是Converter,两者都是可以配置补充的。当解析接口方法时,检查到其类型时,在Retrofit配置的Factory支持集合中选择合适的类型。