zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    kali linux 2019.1 替换burpsuite pro 1.7.37
    java反序列化漏洞实战
    我是一个997程序员
    清晨小悟
    vue webpack配置Error
    USSD 杂记
    WingMoney APP逆向,实现自动话费充值
    保持空杯心态
    解决python在命令行中运行时导入包失败,出现错误信息 "ModuleNotFoundError: No module named ***"
    【转】Mac find 去除 “Permission denied” 信息的方法
  • 原文地址:https://www.cnblogs.com/wytiger/p/10574749.html
Copyright © 2011-2022 走看看