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主要可以扩展三个地方:

  1. 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();
  1. 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();
  1. addCallAdapterFactory

扩展的是对网络工作对象Call Worker的自动转换,把Retrofit中执行网络请求的Call对象,转换为接口中定义的Call对象。
这个转换不太好理解,我们可以对照下图来理解:


 
callAdapter转换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。

posted @ 2019-03-21 21:24  tiger168  阅读(1723)  评论(0编辑  收藏  举报