有很多关于Retrofit源码的分析,但是我总觉得分析的还不够透彻。
环境
AndroidStudio 2.0
准备
gradle:
ompile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.okhttp3:okhttp:3.0.1'
compile 'com.google.code.gson:gson:2.3'
知识点
- retrofit的低耦合
- retrofit的动态代理
retrofit的低耦合
当我们用retrofit的时候都用到下面的代码构建retrofit实例:
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(7676, TimeUnit.MILLISECONDS)
.connectTimeout(7676, TimeUnit.MILLISECONDS)
.addInterceptor(new FakeInterceptor())
.build();
retrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
如果你用到rxjava,因为要将Service返回数据改成Obervable的问题需要这么用:
retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//这个是为了RxJava
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ENDPOINT)
.client(client)
.build();
总结Retrofit主要有以下几种数据创建工厂.
- CallAdapterFactory 创建对service的返回值做除了默认Call的其他数据类型的实例的工厂
- ConverterFactory 创建对请求获得到的数据进行转换的实例的工厂
- CallFactory 创建http请求客户端的实例的工厂(retrofit2.0只允许要求使用okHttpClient)
为什么说retrofit低耦合
如图:
retrofit构建采用建造者模式,上图build method 中将框架使用者add的数据和框架默认使用到CallAdapterFactory,ConverterFactory, CallFactory三种数据进行整合(add),然后创建出retrofit实例返回。
框架使用者通过链式传入定制数据类型,然后通过build进行整合,友好的将框架开发者和使用者进行解耦。
retrofit 2.0 http请求客户端必须使用okhttp,所以如果你要定制http请求客户端,也只能使用OkHttpClient。看下retrofit下的build方法中:
if (callFactory == null) {
callFactory = new OkHttpClient();
}
retrofit的动态代理
当构建好Retrofit实例后,我们会使用create方法,传入对应的Service.class,构建出Http请求。
public <T> T createService(Class<T> clz){
return retrofit.create(clz);
}
//Service
public interface RestApi {
@GET("/")
Call<Teacher> getTeacherById(@Query("id") String id);
}
retrofit只需要创建好interface,然后就能轻易的做到数据请求,就是因为用到了Java 5 的动态代理,核心方法就是create方法。
动态代理:就是代码的自动生成,定义了一个interface后,通过动态代理将接口转换为拥有具体代码的类。即用代码动态生成想要的类。
Java 5的动态代理引入InvocationHandler,在invoke方法中,可以直接获取正在调用对应Method对象。
所以create方法正常执行下面这条语句:
return loadMethodHandler(method).invoke(args);
这里的MethodHandler是做了缓存的:
然后我们再来看MethodHandler.invoke方法:
这里我们可以看出内部请求返回的数据类型是OkHttpCall,然后通过CallAdapter进行数据转换返回。
总结
retrofit 2.0框架中代码风格值得我们去学习,可扩展性和解耦方式做的都非常好。
动态代理主要是用来做方法的增强,还有一个有趣的作用是可以用作远程调用,比如现在有Java接口,这个接口的实现部署在其它服务器上,在编写客户端代码的时候,没办法直接调用接口方法,因为接口是不能直接生成对象的,这个时候就可以考虑代理模式(动态代理)了,通过 Proxy.newProxyInstance代理一个该接口对应的InvocationHandler对象,然后在InvocationHandler的invoke方法内封装通讯细节就可以了。具体的应用,最经典的当然是Java标准库的RMI,其它比如hessian,各种webservice框架中的远程调用,大致都是这么实现的。
如果你想详细了解动态代理参考:
https://www.zhihu.com/question/20794107
http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html