【网络编程】Retrofit创建实例源理

对retrofit的创造实例过程进行源码剖析。

在说之前,介绍一个api,用于判断对象是否为空,然后执行,否则抛出异常,该api在下边很多地方都会出现:

    public static <T> T requireNonNull(T obj, String message) {
        if (obj == null)
            throw new NullPointerException(message);
        return obj;
    }
//用法:Objects.requireNonNull(obj, "obj == null");

Retrofit类

public final class Retrofit {
  // 网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象)
  // 作用:存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

  // Call.Factory 实例,用于生产网络请求器,发送网络请求。默认使用的是okhttp
  final okhttp3.Call.Factory callFactory;
  
  // API 的基础 URL 地址
  final HttpUrl baseUrl;
  
  // Converter.Factory 实例的列表,用于序列化和反序列化对象
  final List<Converter.Factory> converterFactories;
  
  // CallAdapter.Factory 实例的列表,用于支持不同于 Call 的返回类型
  final List<CallAdapter.Factory> callAdapterFactories;
  
  // 回调方法执行的 Executor
  final @Nullable Executor callbackExecutor;
  
  // 是否在创建 Retrofit 实例时进行配置验证
  final boolean validateEagerly;
  
  省略构造函数
    ...

Builder内部类

Builder类的成员变量与Retrofit类的成员变量是对应的,所以Retrofit类的成员变量基本上是通过Builder类的链式调用方法进行配置

public static final class Builder {
    private Platform platform; // 平台对象
    private okhttp3.Call.Factory callFactory; // 网络请求的 Call.Factory
    private HttpUrl baseUrl; // API 的基础 URL 地址
    private List<Converter.Factory> converterFactories = new ArrayList<>(); // 数据转换器工厂列表
    private List<CallAdapter.Factory> adapterFactories = new ArrayList<>(); // 适配器工厂列表
    private Executor callbackExecutor; // 回调方法执行器
    private boolean validateEagerly; // 是否提前验证

    // 构造函数
    public Builder() {
        this(Platform.get()); // 使用 Platform.get() 初始化 Builder↓
    }
    
    // 获取平台对象
    static Platform get() {
        return PLATFORM;
    }

    // Builder 的有参构造函数
    public Builder(Platform platform) {
        this.platform = platform; // 设置平台对象(Android)
      // converterFactories是一个存放数据转换器Converter.Factory的数组,下边添加数据转换器
        converterFactories.add(new BuiltInConverters()); 
      // 初始化数据转换器工厂,
      // BuiltInConverters是一个内置的数据转换器工厂(继承Converter.Factory类)
    }
}

那么我们调用构造函数时,就会调用有参构造函数,参数最终是PLATFORM,这个参数在Platform类中已经定义:

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  // 查找适合的平台
  private static Platform findPlatform() {
    // 判断当前平台是否为 Dalvik(Android)
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() // 如果是 Android 平台,则返回 Android 对象
        : new Platform(true); // 否则返回一个默认的 Platform 对象
  }

  /*下面的可以不用看,直到内部类Android*/
  
  // 是否支持 Java 8 类型
  private final boolean hasJava8Types;
  // MethodHandle 的构造函数
  private final @Nullable Constructor<Lookup> lookupConstructor;

  // 构造函数
  Platform(boolean hasJava8Types) {
    this.hasJava8Types = hasJava8Types;
    // 初始化 lookupConstructor
    Constructor<Lookup> lookupConstructor = null;
    if (hasJava8Types) {
      try {
        // 获取 MethodHandle 的构造函数
        lookupConstructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
        lookupConstructor.setAccessible(true); // 设置为可访问
      } catch (NoClassDefFoundError ignored) {
        // 对于 Android API 24 或 25,Lookup 类不存在,无法调用默认方法
      } catch (NoSuchMethodException ignored) {
        // 假设 JDK 14+,修复了默认方法的问题
      }
    }
    this.lookupConstructor = lookupConstructor;
  }

  // 获取默认的回调方法执行器
  @Nullable
  Executor defaultCallbackExecutor() {
    return null;
  }

  // 获取默认的网络请求适配器工厂列表
  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }

  // 获取默认的网络请求适配器工厂列表的大小
  int defaultCallAdapterFactoriesSize() {
    return hasJava8Types ? 2 : 1;
  }

  // 获取默认的数据转换器工厂列表
  List<? extends Converter.Factory> defaultConverterFactories() {
    return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
  }

  // 获取默认的数据转换器工厂列表的大小
  int defaultConverterFactoriesSize() {
    return hasJava8Types ? 1 : 0;
  }

  // 判断方法是否为默认方法
  @IgnoreJRERequirement // 仅在 API 24+ 上调用
  boolean isDefaultMethod(Method method) {
    return hasJava8Types && method.isDefault();
  }

  // 调用默认方法
  @IgnoreJRERequirement // 仅在 API 26+ 上调用
  @Nullable
  Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, Object... args)
      throws Throwable {
    Lookup lookup =
        lookupConstructor != null
            ? lookupConstructor.newInstance(declaringClass, -1 /* trusted */)
            : MethodHandles.lookup();
    return lookup.unreflectSpecial(method, declaringClass).bindTo(object).invokeWithArguments(args);
  }

  // Android 平台的实现,继承自 Platform。
  //用于接收服务器返回数据后进行线程切换在主线程显示结果
  static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }

    // 获取默认的回调方法执行器
    @Override
    public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
      // 返回一个默认的回调方法执行器
      // 作用:切换线程(子->>主线程),并在UI线程中执行回调方法
    }

    // 调用默认方法
    @Nullable
    @Override
    Object invokeDefaultMethod(
        Method method, Class<?> declaringClass, Object object, Object... args) throws Throwable {
      if (Build.VERSION.SDK_INT < 26) {
        throw new UnsupportedOperationException(
            "Calling default methods on API 24 and 25 is not supported");
      }
      return super.invokeDefaultMethod(method, declaringClass, object, args);
    }

    // Android 平台的主线程执行器
    static final class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());
      // 该Handler是上面获取的与Android UI线程绑定的Handler 
      @Override
      public void execute(Runnable r) {
        handler.post(r);
        // 在UI线程进行对网络请求返回数据处理等操作。
      }
    }
  }
}

baseUrl()

我们通常调用该函数,填入的都是String类型:

    public Builder baseUrl(String baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl));//转换
    }

我们可以看到他会跳转到baseUrl(HttpUrl baseUrl)方法,↓

    public Builder baseUrl(HttpUrl baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();//分割成几个路径碎片
      
      //检查是否以'/'结尾,否则抛出异常
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

addConverterFactory()

    //存储 Converter.Factory
    private final List<Converter.Factory> converterFactories = new ArrayList<>();

    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }

这里用来把转换工厂放入Retrofit的集合中,我们一般在括号内填的是第三方库:GsonConverterFactory.create()

public final class GsonConverterFactory extends Converter.Factory {

  public static GsonConverterFactory create() {
    // 调用create()↓
    return create(new Gson()); ->>步骤2
  }


  public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson); 
    // 创建了一个含有Gson对象实例的GsonConverterFactory ↓
  }

  
  private final Gson gson;
  
  private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
  }

Retrofit默认使用Gson进行解析

client()

    public Builder client(OkHttpClient client) {
      return callFactory(Objects.requireNonNull(client, "client == null"));
    }

    /**
     * Specify a custom call factory for creating {@link Call} instances.
     *
     * <p>Note: Calling {@link #client} automatically sets this value.
     */
    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = Objects.requireNonNull(factory, "factory == null");
      return this;
    }
    //当创建 Retrofit 实例时,会使用这个 callFactory 对象来创建 Call 对象,用于执行网络请求。
  • 25
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xoliu1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值