美文网首页Android技术知识Android文章Android开发
Android小知识-剖析Retrofit中的网络请求流程以及相

Android小知识-剖析Retrofit中的网络请求流程以及相

作者: 爱读书的顾先生 | 来源:发表于2018-11-01 17:15 被阅读323次

    本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,包括年底前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,如果大家想获取最新教程,请关注微信公众号,谢谢!

    在使用Retrofit时,需要创建Retrofit的实例,定义一个网络请求接口并为接口中的方法添加注解,接着通过动态代理生成网络请求对象,关于动态代理的介绍可以查看《Android小知识-剖析Retrofit前的预备知识(静态代理与动态代理)》,在Retrofit中会去解析在网络请求接口中的注解,并配置网络请求参数,通过动态代理拦截生成网络请求对象。

    内部通过网络请求适配器将网络请求对象进行平台适配,比如Android或Java8, 接着通过网络请求执行器发送网络请求,这个网络请求执行器就是Call,这个Call就是对OkHttp的一个封装,底层还是使用OkHttp来发送请求的,服务端返回的数据会经过数据转换器进行解析,在《Android小知识-Retrofit框架的介绍以及使用方式》章节中,使用的是GsonConverter来解析数据,最终转换成Java对象,接着通过回调执行器切换线程,最后客户端在主线程处理返回的结果。

    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://icould.glh/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .build();
    

    上面创建Retrofit的实例在《Android小知识-Retrofit框架的介绍以及使用方式》中已经讲过了,创建Retrofit实例采用的是构建者模式,构建者模式可以将一个对象的复杂构建与表示进行分离,我们进入Retrofit的源码。

    public final class Retrofit {
      private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
    
      final okhttp3.Call.Factory callFactory;
      final HttpUrl baseUrl;
      final List<Converter.Factory> converterFactories;
      final List<CallAdapter.Factory> callAdapterFactories;
      final @Nullable Executor callbackExecutor;
      final boolean validateEagerly;
    
      ...
    }
    

    在具体分析源码前,我们有必要了解Retrofit的几个成员变量。

    serviceMethodeCache是一个LinkedHashMap对象,它的key值是Method,对应的就是Http的请求方法,value是ServiceMethod,ServiceMethod是对网络请求接口内的方法的注解进行解析封装后的对象。

    callFactory是网络请求工厂,在Retrofit内默认的网络请求工厂采用的就是OkHttpClient。

    baseUrl就是网络请求的URL的基地址,baseUrl加上网络请求接口中通过注解定义的相对地址,就组成了一个完整的请求地址。

    converterFactories是数据转换器工厂集合,内部存放的是数据转换器工厂,而数据转换器工厂是用于生产数据转换器,数据转换器的作用就是对请求网络之后的Response进行转换,通过GsonConverter转换成Java对象。

    adapterFactories是网络请求适配器工厂集合,内部存放的是网络请求适配器工厂,网络适配器工厂是用生产网络适配器,网络请求适配器的作用就是将Call对象转换成其他类型,如果需要支持RxJava,就可以将Call对象转换成RxJava平台的Call。

    callbackExecutor是一个线程池,用于执行回调的线程池。

    validateEagerly是一个标志位,是否需要立即解析接口中的方法,具体后面进行讲解,这里先有个印象。

    Retrofit的7个成员变量介绍完了,接着进入Retrofit的Builder类:

    public final class Retrofit {
       ...
       public static final class Builder {
        private final Platform platform;
        private @Nullable okhttp3.Call.Factory callFactory;
        private HttpUrl baseUrl;
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
        private @Nullable Executor callbackExecutor;
        private boolean validateEagerly;
        ...
       }
      ...
    }
    

    Builder类是Retrofit的静态内部类,成员变量platform表示Retrofit适配的平台,主要包括Android和Java 8,默认情况下使用的是Android平台;callFactory表示请求网络的OkHttp的工厂,默认情况下使用OkHttp来完成请求;baseUrl表示网络请求的URL,通过Builder的baseUrl方法传入一个String类型的url,再将String类型的url转换成HttpUrl;converterFactories是数据转换器工厂的集合;callAdapterFactories是网络请求适配器工厂的集合;callbackExecutor用执行异步回调;validateEagerly是一个标志位,表示是否需要立即解析接口中的方法,在使用动态代理时对网络请求接口中方法的注解进行解析时会用到这个标志位。

    public final class Retrofit {
       ...
       public static final class Builder {
        public Builder() {
          this(Platform.get());
        }
        ...
       }
      ...
    }
    

    在Builder的构造函数中通过this传入一个Platform类型,也就是适配的平台,进入Platform的get方法:

     private static final Platform PLATFORM = findPlatform();
    
      static Platform get() {
        return PLATFORM;
      }
    
      private static Platform findPlatform() {
        try {
          Class.forName("android.os.Build");
          if (Build.VERSION.SDK_INT != 0) {
            return new Android();
          }
        } catch (ClassNotFoundException ignored) {
        }
        try {
          Class.forName("java.util.Optional");
          return new Java8();
        } catch (ClassNotFoundException ignored) {
        }
        return new Platform();
      }
    

    Platform是一个单例类,通过findPlatform方法来初始化实例,在静态方法get中返回了PLATFORM静态变量,而PLATFORM静态变量的初始化是在findPlatform方法中完成的,在findPlatform方法中先是通过反射加载"android.os.Build"类,接着返回一个Android平台的Platform对象,我们看一下这个Android对象。

      static class Android extends Platform {
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
          if (callbackExecutor == null) throw new AssertionError();
          return new ExecutorCallAdapterFactory(callbackExecutor);
        }
    
        static class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
      }
    

    在defaultCallbackExecutor中返回一个MainThreadExecutor对象,表示默认的回调方法执行器,这个执行器的作用是从子线程切换到主线程,看下面MainThreadExecutor实现了Executor,是一个线程池,并且内部在创建Handler时传入的是主线程的Looper,通过Looper.getMainLooper()获取主线程Looper,也就是说这个Executor和主线程已经绑定了。继续看Android类中的defaultCallAdapterFactory方法,它表示创建一个默认的网络请求适配器工厂的执行器,在Call对象执行异步请求时,需要一个执行器将异步请求后的数据传递到主线程,defaultCallAdapterFactory放内传入的就是异步请求时进行数据传递所需要的执行器。

    在Builder的无参构造方法内调用了有参构造方法:

         Builder(Platform platform) {
          this.platform = platform;
        }
    

    将创建好的Android平台Platform对象赋值给Builder类的成员变量platform。

    Builder的相关成员变量的初始化已经介绍完毕,接着看看它的build方法:

        public Retrofit build() {
            ...
            //创建OkHttpClient的工厂
            okhttp3.Call.Factory callFactory = this.callFactory;
            if (callFactory == null) {
                callFactory = new OkHttpClient();
            }
            //创建主线程执行器
            Executor callbackExecutor = this.callbackExecutor;
            if (callbackExecutor == null) {
                callbackExecutor = platform.defaultCallbackExecutor();
            }
    
            //添加网络请求适配器工厂
            List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
            callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    
            //添加数据转换器工厂
            List<Converter.Factory> converterFactories =
                    new ArrayList<>(1 + this.converterFactories.size());
            converterFactories.add(new BuiltInConverters());
            converterFactories.addAll(this.converterFactories);
            //创建Retrofit实例
            return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
                    unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
        }
    

    build方法中的注释已经很详细了,判断callFactory是否为空,如果为空,默认创建OkHttpClient,这也说明了Retrofit内部默认是使用OkHttp来进行网络请求的;callbackExecutor默认通过platform的defaultCallbackExecutor方法获取执行器,这里的platform默认是Android平台,在前面讲解Android平台类时,就已经知道了它的defaultCallbackExecutor方法返回的是主线程的执行器,最终数据就是通过主线程的执行器发送到主线程的。

    创建完主线程的执行器后,添加网络请求适配器工厂,这里添加了Android平台的defaultCallAdapterFactory方法传入主线程的执行器,这样在进行异步请求后可以通过主线程的执行器进行数据传递。

    最后就是添加数据转换器工厂,默认添加了一个BuiltInConverters对象,BuiltInConverters表示的是内置的默认的数据转换器工厂。


    838794-506ddad529df4cd4.webp.jpg

    搜索微信“顾林海”公众号,定期推送优质文章。

    相关文章

      网友评论

        本文标题:Android小知识-剖析Retrofit中的网络请求流程以及相

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