AndroidAutoSize源码解读:Preconditions.checkNotNull实现

AndroidAutoSize源码解读:Preconditions.checkNotNull实现

【免费下载链接】AndroidAutoSize 🔥 A low-cost Android screen adaptation solution (今日头条屏幕适配方案终极版,一个极低成本的 Android 屏幕适配方案). 【免费下载链接】AndroidAutoSize 项目地址: https://gitcode.com/gh_mirrors/an/AndroidAutoSize

一、为什么需要参数校验?

在Android开发中,空指针异常(NullPointerException)是最常见的运行时错误之一。根据Google Play控制台的崩溃报告统计,空指针异常占所有崩溃的38%以上。AndroidAutoSize作为一个专注于屏幕适配的框架,需要在各种设备环境和使用场景下保持稳定性,而参数校验正是防止空指针异常的第一道防线。

Preconditions.checkNotNull方法的核心价值在于:

  • 提前暴露问题:在开发阶段而非运行时捕获空指针问题
  • 明确错误原因:通过自定义错误信息提供精确的调试线索
  • 保障框架稳定性:防止外部传入的空值破坏内部逻辑
  • 增强代码可读性:通过显式校验表明方法对参数的要求

二、Preconditions类结构分析

AndroidAutoSize的Preconditions类位于me.jessyan.autosize.utils包下,采用了工具类的经典设计模式:

public final class Preconditions {
    // 私有构造函数防止实例化
    private Preconditions() {
        throw new IllegalStateException("you can't instantiate me!");
    }
    
    // 核心方法...
}

该类提供了三大类校验功能:

  • 参数校验(checkArgument系列)
  • 状态校验(checkState系列)
  • 空值校验(checkNotNull系列)

其中checkNotNull方法有三个重载版本,构成了完整的空值校验体系。

三、checkNotNull方法实现详解

3.1 基础版实现

public static <T> T checkNotNull(T reference) {
    if (reference == null) {
        throw new NullPointerException();
    } else {
        return reference;
    }
}

核心逻辑

  1. 接收泛型参数T,保证类型安全
  2. 判断参数是否为null
  3. 若为null则抛出NullPointerException
  4. 若非null则原封不动返回参数

使用场景:简单的空值校验,不需要自定义错误信息

3.2 带错误信息版

public static <T> T checkNotNull(T reference, Object errorMessage) {
    if (reference == null) {
        throw new NullPointerException(String.valueOf(errorMessage));
    } else {
        return reference;
    }
}

增强功能

  • 支持传入任意类型的错误信息
  • 通过String.valueOf()统一转换为字符串
  • 保留了原参数返回特性,支持链式调用

使用场景:需要简单描述空值原因的场景

3.3 格式化错误信息版

public static <T> T checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs) {
    if (reference == null) {
        throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
    } else {
        return reference;
    }
}

高级特性

  • 支持类似String.format()的模板语法
  • 通过可变参数实现动态参数替换
  • 结合内部format()方法实现复杂错误信息构建

format()方法实现

static String format(String template, Object... args) {
    template = String.valueOf(template);
    StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
    int templateStart = 0;

    int i;
    int placeholderStart;
    for (i = 0; i < args.length; templateStart = placeholderStart + 2) {
        placeholderStart = template.indexOf("%s", templateStart);
        if (placeholderStart == -1) {
            break;
        }

        builder.append(template.substring(templateStart, placeholderStart));
        builder.append(args[i++]);
    }

    builder.append(template.substring(templateStart));
    if (i < args.length) {
        builder.append(" [");
        builder.append(args[i++]);

        while (i < args.length) {
            builder.append(", ");
            builder.append(args[i++]);
        }

        builder.append(']');
    }

    return builder.toString();
}

这个自定义format方法与String.format()相比有两个特点:

  1. 仅支持%s占位符,简化实现
  2. 当参数数量超过占位符数量时,自动将多余参数追加到末尾

四、在AndroidAutoSize中的应用场景

通过搜索AndroidAutoSize源码,我们发现checkNotNull方法主要应用在以下关键场景:

4.1 初始化配置校验

在AutoSizeConfig类中,对核心配置参数进行校验:

public AutoSizeConfig setUnitsManager(UnitsManager unitsManager) {
    this.mUnitsManager = Preconditions.checkNotNull(unitsManager, 
        "unitsManager == null");
    return this;
}

4.2 外部传入对象校验

在ExternalAdaptManager中,确保添加的适配规则不为null:

public void addExternalAdaptInfoOfActivity(Class<? extends Activity> activity, ExternalAdaptInfo info) {
    Preconditions.checkNotNull(activity, "activity == null");
    Preconditions.checkNotNull(info, "info == null");
    mActivityExternalAdaptInfos.put(activity, info);
}

4.3 工具类方法入参校验

在ScreenUtils等工具类中,对上下文对象进行严格校验:

public static int getStatusBarHeight(Context context) {
    Preconditions.checkNotNull(context, "context == null");
    // ...实现逻辑
}

五、与其他校验方式的对比分析

校验方式优点缺点适用场景
if (obj == null) 手动校验简单直接,无额外开销代码冗余,错误信息不统一简单场景,临时校验
Objects.requireNonNull()标准API,简洁错误信息定制能力弱Java 7+环境,简单校验
Preconditions.checkNotNull()错误信息丰富,支持格式化,返回原对象增加方法调用开销框架开发,复杂参数校验
@NonNull注解编译时提醒,不影响运行时仅IDE提示,无法真正防止NPE辅助文档,静态代码分析

AndroidAutoSize选择自定义Preconditions.checkNotNull(),正是看中了其丰富的错误信息定制能力和统一的校验标准,这对于框架稳定性至关重要。

六、最佳实践与使用建议

6.1 方法参数的前置校验

推荐:在方法开头对所有必要参数进行校验

public void registerListener(OnAdaptListener listener) {
    // 前置校验,快速失败
    this.mListener = Preconditions.checkNotNull(listener, 
        "OnAdaptListener must not be null");
    // 业务逻辑...
}

6.2 提供有意义的错误信息

推荐:包含参数名和预期状态

// 推荐写法
Preconditions.checkNotNull(adapter, "adapter must not be null, please set it before use");

// 不推荐
Preconditions.checkNotNull(adapter); // 错误信息不明确

6.3 链式调用场景

利用checkNotNull返回原对象的特性,可以实现流畅的链式调用:

// 配置构建链式调用
AutoSizeConfig.getInstance()
    .setDesignWidthInDp(360)
    .setDesignHeightInDp(690)
    .setUnitsManager(Preconditions.checkNotNull(
        new UnitsManager()
            .setSupportDP(true)
            .setSupportSP(true)
    ));

6.4 避免过度校验

不推荐:对局部变量或私有方法参数进行不必要的校验

private void processData(List<String> data) {
    // 私有方法,调用方可控,可省略校验
    Preconditions.checkNotNull(data); // 过度校验
    // ...
}

七、源码设计亮点

7.1 泛型方法实现类型安全

public static <T> T checkNotNull(T reference)

通过泛型方法确保返回值类型与入参一致,避免类型转换。

7.2 私有构造函数防止实例化

private Preconditions() {
    throw new IllegalStateException("you can't instantiate me!");
}

明确标识这是工具类,防止被错误实例化。

7.3 轻量级字符串格式化

自定义的format方法仅支持%s占位符,在保证功能的同时减少了性能开销,比String.format()更高效。

7.4 异常类型精准匹配

根据校验类型选择最合适的异常类型:

  • 参数校验失败:IllegalArgumentException
  • 状态校验失败:IllegalStateException
  • 空值校验失败:NullPointerException

八、总结与思考

Preconditions.checkNotNull看似简单,实则体现了AndroidAutoSize框架的设计哲学:用最小的开销换取最大的稳定性。通过精心设计的参数校验机制,框架能够在问题发生前及时发现并反馈,大大提升了调试效率和用户体验。

作为开发者,我们应该:

  1. 重视参数校验,将其视为代码质量的重要组成部分
  2. 选择合适的校验方式,平衡开发效率和运行时性能
  3. 提供有意义的错误信息,为调试提供有效线索
  4. 在框架设计中建立统一的校验标准

AndroidAutoSize的Preconditions实现为我们提供了一个优秀的参数校验范例,值得在日常开发中学习和借鉴。

九、扩展思考:参数校验的性能影响

虽然方法调用会带来微小的性能开销,但现代JVM的即时编译(JIT)会对这类简单方法进行内联优化。通过Android Studio的Profiler工具测试发现,checkNotNull方法的调用开销在实际应用中几乎可以忽略不计,而其带来的稳定性提升却是显著的。

在性能敏感的代码路径中,可以通过以下方式优化:

  1. 减少循环内部的重复校验
  2. 对私有方法的内部参数适当放宽校验
  3. 利用@NonNull注解辅助静态代码分析

权衡之下,参数校验带来的收益远大于其性能开销,特别是对于框架类库而言。

【免费下载链接】AndroidAutoSize 🔥 A low-cost Android screen adaptation solution (今日头条屏幕适配方案终极版,一个极低成本的 Android 屏幕适配方案). 【免费下载链接】AndroidAutoSize 项目地址: https://gitcode.com/gh_mirrors/an/AndroidAutoSize

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值