美文网首页Android学习今日看点Android
独特的架构方式,Retrofit源码简析。

独特的架构方式,Retrofit源码简析。

作者: ImmortalHalfWu | 来源:发表于2016-07-28 15:14 被阅读471次
    retrofit2.0

    2016/07/21
    上海
    Read the fucking source code。

        Retrofit,Type-safe HTTP client for Android and Java 。
        GitHub:http://square.github.io/retrofit
    

    开始之前,先回想下一个网络请求的基本姿势(默认框架搭建完成):
    1,生成请求参数,确定接口
    2,利用NetWork模块,发送到指定API
    3,响应成功,反序列
    4,响应失败,做某些处理
    5,线程调度,结果交给前台

    Retrofit作为NetWork框架,也不例外。
    1,以接口+注解的形式,生成请求参数,确定接口
    2,利用CallFactory生成NetWork模块,发送到指定API
    3,响应成功,利用ConverterFactory反序列
    4,响应失败,做某些处理
    5,请求结果经过CallAdapterFactory包装
    6,CallAdapterFactory包装包装后,线程调度,结果交给前台

    目录:
    1,我们配置Retrofit时,到底发生了什么?
    2,Retrofit.create(final Class<T> service)都做了什么?
    3,ServiceMethod 是什么?
    4,OkHttpCall 是什么?
    5,serviceMethod.callAdapter.adapt(okHttpCall)是什么鬼?
    6,CallFactory、okHttpCall、CallAdapter之间的关系?


    问题一:我们配置Retrofit时,到底发生了什么?

    </br>

    //Retrofit构造器
    new Retrofit.Builder()        
    //配置服务器
    .baseUrl(UrlHelp.SERVER_IP)                                     
    //反序列工具生成器
    .addConverterFactory(XmlToJsonConverterFactory.create())
    .//结果包装工具生成器(不大好描述..)        
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())       
    //NetWork工具生成器
    .callFactory(HttpClient())        
    //线程调度
    .callbackExecutor()            
    .build();
    

    ** 配置:**
    ConverterFactory 反序列工具生成器
    CallAdapterFactory 结果包装工具生成器 默认为ExecutorCallAdapterFactory
    okhttp3.Call.Factory NetWork工具生成器 默认为OkHttpClient
    CallbackExecutor 线程调度

    配置的是Retrofit的功能模块,Retrofit将网络请求流程中的各个关节(是的,关节)部位打断,使各个模块之间相关性降到最低,再通过“配置”的方式开放出来,应对复杂的使用环境。

    Retrofit(
      okhttp3.Call.Factory callFactory, 
      HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, 
      List<CallAdapter.Factory> adapterFactories,    
      Executor callbackExecutor, boolean validateEagerly) {  
        this.callFactory = callFactory; 
        this.baseUrl = baseUrl;  
        this.converterFactories = unmodifiableList(converterFactories); 
        // Defensive copy at call site.  
        this.adapterFactories = unmodifiableList(adapterFactories); 
        // Defensive copy at call site.  
        this.callbackExecutor = callbackExecutor;  
        this.validateEagerly = validateEagerly;
    }
    

    .build()方法new Retrofit()实例并返回,new Retrofit()时传入配置信息。


    问题二:Retrofit.create(final Class<T> service)都做了什么?

    </br>

    mRetrofit.create(RetorfitInterfaces.UserInfoServer.class)        
    .sendPost(userId)        
    .enqueue(call);
    

    create(final Class<T> service),传入自定义接口,返回接口实例。
    在外部使用中,这是最直接的感受,实际上返回的是代理对象。

    //仅摘取核心部分
    public <T> T create(final Class<T> service) {      
    ......
      return (T) Proxy.newProxyInstance(
              ...    
              new InvocationHandler() {        
                .....
                @Override 
                public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
                    ......
                    //加载ServiceMethod
                    ServiceMethod serviceMethod = loadServiceMethod(method);
                    //加载OkHttpCall 
                    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
                    //调用callAdapter.adapt(okHttpCall)
                    return serviceMethod.callAdapter.adapt(okHttpCall);
            }
          });
    }
    

    这部分源码写的很直观,简单来说当调用接口中的方法时,都会运行InvocationHandlerinvoke()方法。

    重点就在invoke(Object proxy, Method method, Object... args)方法中的三句代码:

    ServiceMethod serviceMethod = loadServiceMethod(method);
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    return serviceMethod.callAdapter.adapt(okHttpCall);


    问题三:ServiceMethod 是什么?

    </br>
    (以下省略适配、优化等细节代码)

    //调用Retrofit.loadServiceMethod(method);加载ServiceMethod;
    serviceMethod = loadServiceMethod(method);
    
    ServiceMethod loadServiceMethod(Method method) {
      ServiceMethod result;
       ....
          //通过 ServiceMethod.Builder构造器创建实例
          result = new ServiceMethod.Builder(this, method).build();
       ....
      return result;
    }
    
    public Builder(Retrofit retrofit, Method method) {
    //持有了retrofit实例,retrofit持有前面说到的各配置组件,
    //也就是说ServiceMethod相当于持有各配置组件,
    //变相的将四大组件组装在了一起。
      this.retrofit = retrofit;
    
      ..注解解析相关...
    }
    
    public ServiceMethod build() {
    .....
    
    //创建CallAdapter实例,createCallAdapter()是ServiceMethod.Builder的私有方法,在此简写
      callAdapter = createCallAdapter(){
         ....
         //调用了Retrofit实例的CallAdapter();CallAdapter()是Retrofit的公共方法,在此简写
         return retrofit.callAdapter(returnType, annotations){
             ...
                   //Retrofit利用配置中的CallAdapterFactory获取CallAdapter实例
                   return CallAdapterFactory.get();
               };
       };
    
    ......
    
      //创建responseConverter 反序列工具实例,createResponseConverter()是ServiceMethod.Builder的私有方法,在此简写
      responseConverter = createResponseConverter(){
                ....
          //调用Retrofit实例的responseBodyConverter()方法
          return retrofit.responseBodyConverter(responseType, annotations){
                        ....
                       //利用converterFactory工厂创建反序列工具
                        return converterFactory.responseBodyConverter();
                 }
       };
    
    ...注解相关...  
    
      //调用ServiceMethod的构造函数ServiceMethod(Builder builder);创建实例
       return new ServiceMethod<>(this);
    }
    

    //ServiceMethod.Builder构造器(注意还不是ServiceMethod)持有了Retrofit实例,CallAdapter实例,responseConverter 反序列工具实例。

    //ServiceMethod构建方法,参数是构造器
    ServiceMethod(Builder<T> builder) {
              this.callFactory = builder.retrofit.callFactory();//持有CallFactory实例
              this.callAdapter = builder.callAdapter;            //持有CallAdapter实例
              this.baseUrl = builder.retrofit.baseUrl();          //持有BaseUrl
              this.responseConverter = builder.responseConverter;//持有反序列工具
              ....注解相关
    }
    

    至此,ServiceMethod实例创建完毕,ServiceMethod变相的将各模块组装在一起。


    问题四:OkHttpCall是什么?

    </br>
    先说两个概念:

    interface okhttp3.Call{
           enqueue(Callback responseCallback);
           execute();
           request();
           isExecuted();
           isCanceled();
           cancel();
    }    
    
    interface retrofit2.Call{
           同上;
           clone();
    }        
    

    1,retrofit2.Call与okhttp3.Call区别就是多了个clone方法,retrofit2.Call需要clone,才能再次使用。
    2,OkHttpCall 实现了retrofit2.Call。
    3,CallFactory创建的是okhttp3.Call实例,OkHttpClient实现了okhttp3.Call。
    WTF??看代码。

    (以下省略适配、优化等细节代码)

    //直接调用构造方法
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    
    OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
           this.serviceMethod = serviceMethod;  //持有了ServiceMethod实例
           this.args = args;//注解相关
    }
    

    OkHttpCall持有serviceMethod实例,就这样。但OkHttpCall 实现了retrofit2.Call,有必要看一下enqueue(Callback responseCallback);execute();

    //外部传入callBack,结果回调
    enqueue(final retrofit2.Callback<T> outCallback){
            //Retrofit NetWork模块实际使用的还是okhttp3.Call,retrofit2.Call只是对外放出的包装
            okhttp3.Call call = createRawCall(){
                    //Retrofit 默认callFactory为OkHttpClient
                    return serviceMethod.callFactory.newCall(request);
            };
            //利用okhttp3.Call发送请求,并传入新的CallBack();
            call.enqueue(
                    new okhttp3.Callback() {
                            //成功
                            onResponse(okhttp3.Response rawResponse){
                                //parseResponse(rawResponse)是将请求结果反序列,内部调用ServiceMethod中的responseConverter,也就是配置里的反序列化工具生成JavaBean。
                                rawResponse = parseResponse(rawResponse)
                                //将反序列化后的JavaBean传给前台
                                outCallback.onResponse(rawResponse);
                            }
                            //失败
                            onFailure(Throwable e){
                                //将错误信息传给前台
                                outCallback.onFailure(e);
                            }
                    }
            )
    }
    
    execute(){
    
            ...与enqueue大致相同, 也是利用CallFactory生成okhttp3.Call,调用okhttp3.Call.execute()
    
    }
    

    so:

    1,OkHttpCall实现Retrofit.Call接口
    2,CallFactory生成的Call对象为Okhttp3.Call接口
    3,OkHttpCall持有CallFactory生成的Call对象
    4,OkHttpCall在enqueue,execute方法中实际调用的是CallFactory生成的Call对象发送请求,OkHttpCall本身并没有NetWork的功能
    5,所以,OkHttpCall只是适配器,或者说包装器,外部使用Retrofit.Call,Retrofit.Call内部使用Okhttp3.Call,Retrofit.Call与Okhttp3.Call之间,由OkHttpCall调度
    6,OkHttpCall实现Retrofit.Call接口,与外部来说,无需关心NetWork到底是如何发送的


    问题五:

    serviceMethod.callAdapter.adapt(okHttpCall)是?

    </br>
    先回头撸一下

            mRetrofit
            //返回代理对象
            .create(RetorfitInterfaces.UserInfoServer.class)
            //serviceMethod.callAdapter.adapt(okHttpCall)返回retrofit2.Call对象
            .sendPost(userId)
            //调用返回的retrofit2.Call的enqueue方法
            .enqueue(call);
    

    没毛病。

    serviceMethod.callAdapter由Retrofit.CallAdapterFactory创建(上面源码有提到)。 而CallAdapterFactory可由外部配置,默认ExecutorCallAdapterFactory。

    (以下省略适配、优化等细节代码)

    //默认ExecutorCallAdapterFactory.adapt,创建返回了ExecutorCallbackCall实例
    @Override public <R> Call<R> adapt(Call<R> call) {
            //call就是okHttpCall
           return new ExecutorCallbackCall<>(callbackExecutor, call);
    }
    
    //看看ExecutorCallbackCall又是什么,一个 Retrofit2.Call<T>实现类,
    class ExecutorCallbackCall<T>implements Retrofit2.Call<T>{
    
            //构造函数,callbackExecutor配置中的线程池,delegate就是okHttpCall
            ExecutorCallbackCall(Executor callbackExecutor, retrofit2.Call<T> delegate) {                this.callbackExecutor = callbackExecutor;                this.delegate = delegate;        }
            
             //Retrofit2.Call<T>接口中的方法,发送异步请求,参数outCallBack是外部传入的回调接口
             enqueue(final Callback<T> outCallback){
                    //利用delegate,其实就是okHttpCall发送请求,又是包装new Callback()
                    delegate.enqueue(new Callback<T>() {
                        //成功
                         onResponse(Call<T> call, final Response<T> response) {
                                //线程调度
                                 callbackExecutor.execute(new Runnable() {
                                        public void run() {
                                        //传给前台
                                          outCallBack.onResponse(
                                                  ExecutorCallbackCall.this, response
                                          );
                                        }
                                  }
                              }
                        //失败
                          onFailure(Call<T> call, final Throwable t){
                                //线程调度
                                callbackExecutor.execute(new Runnable() {
                                    public void run() {
                                        outCallBack.onFailure(ExecutorCallbackCall.this, t);
                                    }
                                });
                          }
                );
            }
             // ****Retrofit2.Call<T>接口中的方法,**发送同步请求**
            Response<T> execute(){
                        //delegate 就是okHttpCall
                         return delegate.execute();
            }
    }
    

    1,serviceMethod.callAdapter.adapt(okHttpCall)返回Retrofit2.Call实例,默认ExecutorCallbackCall
    2,ExecutorCallbackCall实例中持有okHttpCall的实例
    3,ExecutorCallbackCall实例中的enqueue,execute方法,方法中实际操作的还是OkHttpCall对应的方法。
    4,ExecutorCallbackCall将请求结果通过制定线程(配置中的CallbackExecutor)发送到前台


    问题六:CallFactory、okHttpCall、CallAdapter之间的关系?

    </br>
    从上向下的包装关系,,类似装饰模式:
    ** 外部调用**
    ** CallAdapterFactory.CallAdapter.Retrofit.Call**
    ** 包装**
    okHttpCall.Retrofit.Call
    ** 包装**
    CallFactory.okhttp3.Call

                          外部调用                                 
    |---------------------------------------------------|
    |              CallAdapter.Retrofit.Call            |
    |     |---------------------------------------|     |
    |     |        okHttpCall.Retrofit.Call       |     |
    |     |     -----------------------------     |     |
    |     |     |  CallFactory.okhttp3.Call |     |     |
    |     |     -----------------------------     |     |
    |     |                                       |     |
    |     |---------------------------------------|     |
    |                                                   |
    |---------------------------------------------------|
    
    

    CallFactory.okhttp3.Call面向发送请求,不关心结果处理
    CallAdapterFactory.CallAdapter.Retrofit.Call面向返回结果,不关心发送
    OkHttpCall.Retrofit.Call作为中间件,将两者联系起来
    **外部实际调用的是CallAdapter生成的Retrofit.Call **

    相关文章

      网友评论

      • 捡淑:马克
      • 小彤花园:看到那句 Read the fucking source code好像很熟悉的样子😂wiki 上的RTFM那条还是我编辑的,当然其中包括了 RTFS :smiley:
        ImmortalHalfWu:@小彤花园 😄你的评论完美回答了 “求Read the fucking source code出处?”,你的开源贡献比我强太多了。

      本文标题:独特的架构方式,Retrofit源码简析。

      本文链接:https://www.haomeiwen.com/subject/vwuajttx.html