美文网首页
基于Android Studio和@NonNull/@Nulla

基于Android Studio和@NonNull/@Nulla

作者: Dio丶 | 来源:发表于2019-03-24 21:34 被阅读0次

    前言

    前段时间,我发现业务代码中有许多疑似多余的空(null)检查,为什么说是疑似呢?

    师傅曾说过:
    当你发现一个问题的时候,先别太早下结论,首先确定它是不是个问题,再确定问题的本质,最后由此想出解决方法。
    程序员本质上也就是干这两件事,发现问题和解决问题。
    

    故全文围绕这两个问题展开:

    1. 多余的空检查是什么,为什么?
    2. 怎么样避免多余或遗漏的空检查?

    AOSP和JDK的代码实践可算是千锤百炼,通过分析和总结归纳,我比较认可的以下方式:

    1. 在私有或包内访问域的方法参数,使用基于Android Studio和@NonNull/@Nullable注解的Android静态检查方法,表明方法是否处理null参数,提升合作效率和代码语义。
    2. 在公有的方法参数(如SDK的API方法),使用正常的空检查,能处理的情况提前返回,不能处理的情况直接抛出IllegalArgumentException,由调用者负责处理。

    最后,我们再简单谈谈其他空检查的注解和Android Studio的静态检查工具的其他用法。

    问题三连:多余空检查是什么,为什么,怎么样?

    代码源于现实生活,让我们举个栗子。

    多余的空检查就像坐地铁过安检,收益是需要权衡的。
    多次安检固然比较安全,但是也会带来效率上的开销。
    一次检查基本上可以拦截大部分问题,后续检查的收益就比较低了。
    

    每一句代码都是需要深思熟虑后才去写的。早期写代码大家可能就是报着“多做无害”的心态,反正不会崩溃。这样容易写出很多冗余代码,最终导致代码腐烂。
    多余空检查的开销我没有仔细研究过,应该就是一两个计算机指令,最终换算成CPU时钟周期的计算,在当前CPU性能普遍比较高的今天,也不在话下,只能说,这么做很不极客Geek。

    如何避免多余的空检查?

    言归正传,如何避免多余的空检查,首先需要知道需要检查的内容,基本上就是外部输入参数或者外部函数返回值,而相对地,不太需要检查的是内部的参数和函数返回值。

    1. 外部入参和返回值处理:
      外部入参和返回值都属于外部输入,跨越信任边界,可视为来源不可信,必须校验其合法性。在入参明显与函数职责不合法,可直接返回IllegalArgumentException,认为这是程序员的逻辑错误,比如对拷贝数组的函数传入null,null参数不在拷贝数组的函数处理范围内,传入null是要找茬?
    2. 内部的参数和函数返回值处理:
      我们不能明确或要求每个函数都处理非空的入参,或者返回值为非空,那么就需要使用额外的方式,约定函数的信息,在Java中,一种比注释更好的方式是注解。

    下面主要介绍,基于@NonNull/@Nullable注解以及配合Android Studio的静态检查工具,形成了程序的“约定”。

    主要思路

    1. 使用android.annotation或android.support.annotation包下面的@NonNull和@Nullable,对方法或参数进行注解。
    2. 使用Android Studio的inspection静态检查工具,在编码期进行静态检查,及时发现不合理的冗余检查或遗漏检查。

    优缺点

    • 优点:

      • 提前发现问题:在编码期就能及时发现不合理的冗余检查或遗漏检查,成本较低。
      • 开销小:@NonNull和@Nullable为源码注解,在编译期就会被编译期无视,不增加运行时开销。
    • 缺点:

      • 约束力较差:仅仅以静态扫描的告警形式表现,而不是编译时error,约束力较弱。
      • 依赖Android Studio:依赖于体量较大的IDE,且需要团队成员均使用才能发挥较好的效果。如果能有独立的命令行lint工具,就最好不过。

    配置方法

    1. 导入对应的annotation包: 在APP侧,需要增加对Android support包的依赖;在framework开发中,可以直接使用android.annotation包。

    2. 在Analyze -> Inspection Code,配置inspection静态扫描工具对应的注解类为android.annotation或android.support.annotation包的注解,如下图所示:

    配置注解类.png inpection扫描配置.jpg
    自定义注解类.png
    1. 在编码中,通过选择自定义的规则,扫描文件或者文件夹就可以得到扫描报告,并进行快速修改,如下图所示:
    NonNull传参.jpg NonNull检查.jpg 扫描结果.jpg

    扩展杂谈

    从上文Android Studio的配置可以看出两点:

    1. 其实有其他null检查的注解方式,如Jetbrain提供的注解和Java提供的注解等可以选择;
    2. inspection静态扫描不仅支持null扫描,还有其他非常丰富的规则集可以运用到日常的代码开发中。

    这里先做简单地介绍,后面有机会统一学习和实践后再做详细探讨。

    • Android Studio由Jetbrain公司开发,被Google收购,提供了org.jetbrain.annotation注解,搭配Analyze -> infery nullibility功能进行使用,但需要导入org.jetbrain的jar包。
    • java提供了javax.validation.annotation,但不在Android支持的API范围内(Android对Java的包是有选择的引入,特别是javax扩展包,这里不做详解),和JSR305库提供注解,同样需要额外导入jar包。
    • inspection静态扫描工具非常好用,规则配置非常灵活,且可以导入导出配置文件,适合团队使用,后面会分享具体的配置细节。

    个人实践总结和心得

    1. 工具只是辅助工具,不要过度依赖工具,最后还是得根据实际情况,由开发者进行判断。毕竟工具只是为了解决人类在某些方面脑力有限而做出来的工具,像调用栈和参数这种东西,人脑也记不了几层。
    2. 越早发现问题成本越低。比起在调试、测试、Beta、上线商用时被发现问题,编码期发现和解决问题的成本简直不要太低,差了好几个数量级呀。所以越早发现问题成本是最低的,防患于未然,做扁鹊大哥吧。
    3. 敬佩Google以开发者为核心的生态布局。在Android开发中,Google的套件,如Android Studio的强大功能(跟它的卡和吃内存是有关系的),framework开发用到的Gerrit(代码检视平台)和repo(多代码仓操作脚本)等等,实在是让人觉得伟大。

    相关文章

      网友评论

          本文标题:基于Android Studio和@NonNull/@Nulla

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