Retrofit原理
Retrofit原理解析最简洁的思路
Retrofit 工作原理总结
从架构角度看Retrofit的作用、原理和启示
Retrofit主要是在create方法中采用动态代理模式实现接口方法;这个过程构建了一个ServiceMethod对象,根据方法注解获取请求方式、参数类型、参数注解,然后拼接网络请求的链接;当我们主动发起网络请求的时候会调用okhttp发起网络请求,okhttp的配置包括请求方式、URL等在Retrofit的RequestBuilder的build()方法中实现,并发起真正的网络请求。
大概原理
通过java接口以及注解来描述网络请求,并用动态代理的方式,在调用接口方法前后(before/after)注入自己的方法,before通过接口方法和注解生成网络请求的request,after通过client调用相应的网络框架(默认okhttp)去发起网络请求,并将返回的response通过converterFactorty转换成相应的数据model,最后通过calladapter转换成其他数据方式(如rxjava Observable)
· 动态代理
代理对象拦截真实对象的方法调用,在真实对象调用前/后实现自己的逻辑调用
见Retrofit.create()方法
· 重点类
1.Retrofit类: 创建接口api的动态代理对象(create()返回api service动态代理对象,调用代理对象上的方法时,会触发代理对象上的invoke方法,这里面会封装好OKHttpCall对象,OKHttpCall的数据返回根据calladapter转换为Observable)
2.ServiceMethod类: 解析方法和注解,生成HttpRequest(toRequest方法;创建responseConverter(将response流转换为String或者实体类); 创建callAdapter(转换为rxjava observable)
3.OKHttpCall: 封装okhttp3的调用
4.Rxjava2CallAdapter: 转换成Observable (BodyObservable会对http code做检查,如果错误直接走onError流程)
或者
1. 通过建造者模式构建一个Retrofit实例,配置baseUrl,callAdapterFactory(将代理返回的Call对象转化为其他,比如Rxjava的Observer),converterFactory(结果的转化器,将请求的结果转化为特定的对象时使用,比如GsonConverterFactory)
2.通过Retrofit对象的create(Class<T> service)方法返回一个Service的动态代理对象,在调用service的方法的时候,就是调用动态代理的invoke方法。
3.调用代理的invoke方法的时候,会将method进行解析,解析我们在接口里面配置的各种注解,最后构造成ServiceMethod对象,并将结果缓存起来,下次再次调用就不用解析了。ServiceMethod对象可以生成Request对象,所以将ServiceMethod对象注入到OkHttpCall,然后通过callAdapter转化为用户希望得到的返回对象,默认是直接返回Call对象。
4.返回Call对象之后,我们再调用execute或者enqueue方法,前者是同步请求,后者是异步请求,再方法里面会调用Okhttp的网络请求方法。
综上所述,Retrofit就是一个封装了Http请求的脚手架,底层的网络请求都是使用的Okhttp,本身只是简化了用户网络请求的参数配置等,还能与Rxjava相结合,使用起来更加简便。
---------------------
功能扩展
我们先来看Retrofit能扩展哪些功能,Retrofit主要可以扩展三个地方:
- OkHttpClient
Retrofit使用OkHttpClient来实现网络请求,这个OkHttpClient虽然不能替换为其他的网络执行框架比如Volley,但是Retrofit允许我们使用自己扩展OkHttpClient,一般最常扩展的就是Interceptor拦截器了
OkHttpClient mClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
try {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Accept-Charset", "UTF-8");
builder.addHeader("Accept", " application/json");
builder.addHeader("Content-type", "application/json");
Request request = builder.build();
return chain.proceed(request);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Config.DOMAIN)
.addConverterFactory(GsonConverterFactory.create())
.client(mClient)
.build();
- addConverterFactory
扩展的是对返回的数据类型的自动转换,把一种数据对象转换为另一种数据对象。
在上述场景中,GsonConverterFactory可以把Http访问得到的json字符串转换为JavaBean,这个JavaBean是在INetApiService接口中要求的的。
如果现有的扩展包不能满足需要,可以继承Retrofit的接口。retrofit2.Converter<F,T>,自己实现Converter和ConverterFactory。
在创建Retrofit对象时,可以插入我们自定义的ConverterFactory。
//retrofit对象
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Config.DOMAIN)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(YourConverterFactory.create())//添加自定义Converter
.build();
- addCallAdapterFactory
扩展的是对网络工作对象Call Worker的自动转换,把Retrofit中执行网络请求的Call对象,转换为接口中定义的Call对象。
这个转换不太好理解,我们可以对照下图来理解:
Retrofit本身用一个OkHttpCall的类负责处理网络请求,而我们在接口中定义需要定义很多种Call,例如Call<BizEntity>,或者Flowable<BizEntity>等,接口里的Call和Retrofit里的OkHttpCall并不一致,所以我们需要用一个CallAdapter去做一个适配转换。
(Retrofit底层虽然使用了OkHttpClient去处理网络请求,但她并没有使用okhttp3.call这个Call接口,而是自己又建了一个retrofit2.Call接口,OkHttpCall继承的是retrofit2.Call,与okhttp3.call只是引用关系。这样的设计符合依赖倒置原则,可以尽可能的与OkHttpClient解耦。)
这其实是Retrofit非常核心,也非常好用的一个设计,如果我们在接口中要求的函数返回值是个RxJava的Flowable对象
public interface INetApiService {
@GET("/demobiz/api.php")
Flowable<BizEntity> getBizInfo(@Query("id") String id);
}
那么我们只需要为Retrofit添加对应的扩展
//retrofit对象
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Config.DOMAIN)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
就能得到Flowable类型的callWorker对象
//用retrofit加工出对应的接口实例对象
INetApiService netApiService= retrofit.create(INetApiService.class);
···
//调用接口函数,获得网络工作对象
Flowable<BizEntity> callWorker= netApiService.getBizInfo("id001");
在这里,callAdapter做的事情就是把retrofit2.Call对象适配转换为Flowable<T>对象。
同样,如果现有的扩展包不能满足需要,可以继承Retrofit的接口retrofit2.CallAdapter<R,T>,自己实现CallAdapter和CallAdapterFactory。