Android Lint 基础:检查类型、内置规则与命令行运行

说到 Android Lint,我觉得它就像是项目里的一个「静态代码巡查员」。你写代码的时候,它不会说话,但等你一运行检查,它就能把潜藏的问题一个个揪出来。性能隐患、安全漏洞、甚至拼写错误——它都能管。我个人习惯在每次提交代码前跑一遍 Lint,效果比人工 review 要稳定得多。

Lint 检查类型

Android Lint 把检查分了 6 大类。为什么要这么分?因为不同问题的影响面不一样,你修复的时候优先级也不同。我过去在项目中遇到过把「性能」问题当成小 bug 忽略,结果上线后卡顿反馈直接爆了。所以分类是有意义的。

检查类型 说明 我比较关注的点
Correctness(正确性) 代码逻辑、API 误用、资源缺失等 这是最高优先级,我会在 CI 门禁里设成 error
Performance(性能) 内存泄漏、布局过度绘制、冗余对象创建 很多新人不注意 StringBuilder 拼接,跑一次 Lint 就暴露了
Security(安全) WebView 设置、明文通信、导出组件 以前我踩过 WebView 允许 file 协议的坑,后来就加了这条规则
Usability(可用性) TextView 缺失 contentDescription、控件点击区域过小 无障碍设计其实不难,但很容易被忽略
Accessibility(无障碍) 与 Usability 类似,但更侧重辅助功能 其实很多团队把这俩合并了,但 Lint 是分开的
Internationalization(国际化) 硬编码字符串、缺失翻译、排版方向问题 你想想看,如果你的 app 要出海,这条很重要

内置规则概览

Android Lint 内置了 300+ 条规则。你不需要全部记住,但有几类是我每次必查的:

  • Nullability 相关:NullArgument、Nullable 标注检查。我曾经被一个 nullable 返回值坑到崩溃,现在 Lint 直接帮我拦住。
  • 布局性能:NestedWeights、UselessParent、Overdraw。说白了就是减少层级、减少重绘。
  • 资源冗余:UnusedResources、UnusedIds。项目大了之后,残留的资源会塞爆 APK。
  • 线程安全:HandlerLeak、ObsoleteSdkInt。Handler 导致的内存泄漏,你肯定见过。
  • Gradle 相关:GradleDependency、GradleCompatible。建议把 gradle 版本检查也加到 Lint 里。

这些规则默认是开启的,你可以在 lint.xml 里调整严重级别。嗯,这里要注意:不要把错误改得太宽松,否则 Lint 就形同虚设了。

命令行运行方式

我平时最常用命令行跑 Lint,因为便于集成到 CI 流水线。有三种方式:

方式一:通过 Gradle 任务

./gradlew lint                    # 所有 build variant 都检查
./gradlew lintDebug               # 只检查 debug 变体
./gradlew lintRelease             # 通常 release 变体要求更严格

结果会生成 HTML 和 XML 报告,默认在 build/reports/lint-results.html。

方式二:直接调用 lint 命令行工具

lint --check "Correctness,Performance" --report ./lint-report.html ./app/src/main

这个适合你做自定义扫描,比如只检查某个模块。我个人习惯在 shell 脚本里封装一下,把参数写清楚。

方式三:结合 Gradle 的 LintOptions 配置

android {
    lintOptions {
        abortOnError true                  // 发现错误就停止构建
        xmlReport false
        htmlReport true
        htmlOutput file("lint-report.html")
        checkReleaseBuilds true
        // 我曾经把某个规则设成 "ignore",结果上线出事了
        disable 'MissingTranslation'
        enable 'RtlHardcoded'
    }
}

避坑提醒:我曾在项目中把 abortOnError 设为 false,结果 CI 虽然通过了,但 Lint 错误被掩盖。后来发现线上 app 有 NullPointerException,查下来就是 Lint 报过的。所以建议正式构建一定要 abortOnError true。

另外,你可以用 ./gradlew lintVitalRelease 只检查 release 变体里的致命问题,速度会快很多。

使用频率最高的几个命令行参数

参数 作用
--check 指定要运行的检查类型,比如 --check "Correctness"
--disable 临时禁用某条规则,我用它来屏蔽已知的假阳性
--enable 启用某条规则,比如你需要特别关注国际化时
--report 自定义报告输出路径
--quiet 只输出错误,不输出警告信息,适合 CI 日志

一点经验:当你第一次在项目里跑全量 Lint,可能会看到几百个警告。不要慌。先修 error,再把 warning 按类型分批修。我一般分三天:第一天修正确性和安全,第二天修性能,第三天扫尾巴。这样团队压力小,效果反而好。

Android Lint 基础结构 Android Lint 检查类型分类 正确性 性能 & 安全 可用性 & 国际化 内置规则 300+ Null安全 布局性能 命令行运行 Gradle 任务 lint 命令行 HTML/XML 报告

小技巧:如果你嫌 Lint 报告太长,可以用 --baseline 参数。先跑一次生成 baseline.xml,之后 Lint 只会报告新增的问题。这个在大型遗留项目里特别好用,我们团队靠它慢慢把旧债还清。

最后,记得查看 $ANDROID_HOME/tools/bin/lint 的完整文档。你可以在终端里输入 lint --help 得到所有参数列表。对于刚接触 Lint 的团队,我建议从 ./gradlew lintDebug 开始,只看 debug 变体,等稳定后再开启全部变体。