Android网络框架——Retrofit源码分析

Retrofit源码解析

Retrofit是一个RESTFUL的HTTP网络请求框架(基于OkHttp)。

Retrofit的具体流程如下:

  1. 创建Retrofit实例
  2. 创建网络请求接口的实例(通过解析注解配置网络请求参数)
  3. 发送网络请求
  4. 解析数据
  5. 切换线程
  6. 处理结果

下来我们一一进行讲解。

一、创建Retrofit实例

通过内部类Builder(建造者模式)创建出一个Retrofit实例,其具体创建过程配置了一下参数:

  • 平台类型对象(Platform—Android)
  • 网络请求的url地址(baseUrl)
  • 网络请求工厂(callFactory)—默认使用OkHttpCall
  • 网络请求适配器工厂的集合(adapterFactories)—默认是ExecutorCallAdapterFactory
  • 数据转换器工厂集合(converterFactories)—本质是配置了数据转换器工厂
  • 回调方法执行器(callbackExecutor)—默认回调方法执行器的作用是:切换线程(子线程→主线程)
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

如何生成一个Retrofit实例,我们只需看build方法即可:

    public Retrofit build() {
   
    //检查网络请求的url是否为空,假如为空直接抛出异常。
      if (baseUrl == null) {
   
        throw new IllegalStateException("Base URL required.");
      }
	//配置网络请求工厂(callFactory)
      okhttp3.Call.Factory callFactory = this.callFactory;
      //如果在创建实例时没有指定callFactory,默认使用OkHttp进行网络请求
      if (callFactory == null) {
   
        callFactory = new OkHttpClient();
      }
	//配置回调方法执行器(callbackExecutor)
      Executor callbackExecutor = this.callbackExecutor;
      //如果在创建实例时没有指定callbackFactory,默认使用Platform的默认的callbackFactory
      //我们安卓开发就是Android平台默认的callbackExecutor
      if (callbackExecutor == null) {
   
        callbackExecutor = platform.defaultCallbackExecutor();
      }

	//配置网络请求适配器工厂(CallAdapterFactories)
	//向该集合中添加创建实例时的自定义适配器工厂
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      //向该集合中 添加platform默认的适配器工厂
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
      //请求适配器工厂集合存储顺序:自定义 1 适配器工厂、自定义 2 适配器工厂...默认适配器工厂(ExecutorCallAdapterFactory)

	//配置数据转换器工厂(converterFactory)
	//实现创建好大小合适的Converter.Factory集合
      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

	//依次添加默认数据转换器工厂(BuiltInConverters()),自定义工厂(this.converterFactories),平台默认数据转换器工厂(platform.defaultConverterFactories())
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

	//最终返回一个 Retrofit 的对象,并传入上述已经配置好的成员变量 
      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }

二、创建网络请求接口的实例(通过解析注解配置网络请求参数)

Retrofit采用了外观模式统一调用创建网络请求接口实例和网络请求参数配置的方法,具体过程如下:

  1. 动态创建网络请求接口(代理模式—动态代理#invocationHandler对象#invoke())
  2. 创建ServiceMethod对象(建造者模式&单例模式(缓存机制))
  3. 对serviceMethod对象进行网络请求参数配置:通过解析网络请求接口方法的参数、返回值和注解类型,从Retrofit对象中获取对应的网络请求的url地址、网络请求执行器、网络请求适配器和数据转换器(策略模式)
  4. 创建一个OkHttpCall类型的网络请求对象
  5. 对OkHttpCall对象加入线程切换的操作,便于接受数据后通过Handler从子线程切换到主线程从而对返回的数据结果进行处理(装饰模式)
GitHubService service = retrofit.create(GitHubService.class);

//listRepos是GitHubService.class中的一个方法
Call<List<Repo>> repos = service.listRepos("octocat");

表面看我们只写了短短两行,但实际内部做了很多处理!!!

步骤1.动态创建网络请求接口

public <T> T create(final Class<T> service) {
   
//1.检验service的方法,具体请看下方validateServiceInterface(service)方法的讲解。
  validateServiceInterface(service);
    
  //通过动态代理创建了网络请求接口的实例
  return (T)
      Proxy.newProxyInstance(
          service.getClassLoader(),//动态生成接口的实现类
          new Class<?>[] {
   service},//动态创建实例
          new InvocationHandler() {
   	//将代理类的实现交给InvocationHandler类作为具体实现
            private final Platform platform = Platform.get();
            private final Object[] emptyArgs = new Object[0];

            @Override
            public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
                throws Throwable {
   
              //如果该方法是来自 Object 的方法,则遵循正常调用。
              if (method.getDeclaringClass() == Object.class) {
   
                return method.invoke(this, args);
              }
              args = args != null ? args : emptyArgs;
                //2.如果该方法是默认方法也直接调用,否则加载该方法(loadServiceMethod()返回的是一个ServiceMethod对象)后再调用(实质就是进行网络请求)
              return platform.isDefaultMethod(method)
                  ? platform.invokeDefaultMethod(method, service, proxy, args)
                  : loadServiceMethod(method).invoke(args);
            }
          });
}

注释1: 验证Service类的方法

  private void validateServiceInterface(Class<?> service) {
   
      //检验service是不是接口,如果不是抛出异常
    if (!service.isInterface()) {
   
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }

      	//检验service以及其所有的父接口是否具有泛型,如果有抛出异常
    Deque<Class<?>> check = new ArrayDeque<>(1);
    check.add(service);
    while (!check.isEmpty()) {
   
      Class<?> candidate = check.removeFirst();
      if (candidate.getTypeParameters().length != 0) {
   
        StringBuilder message =
            new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
        if (candidate != service) {
   
          message.append(" which is an interface of ").append(service.getName());
        }
        throw new IllegalArgumentException(message.toString());
      }
      Collections.addAll(check, candidate.getInterfaces());
    }

     //初始化所有service中非静态方法和非默认方法。
    if (validateEagerly) {
   
      Platform platform = Platform.get();
      for (Method method : service.getDeclaredMethods()) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值