4、规则配置入门:Lint 的 lint.xml 配置、Detekt 的 detekt.yml 配置
规则配置,说白了就是把工具的“检查清单”按你的项目胃口调一调。默认配置往往要么太松(漏检一堆问题),要么太紧(跑一次恨不得报几百个错误)。我个人习惯,先把门打开,然后慢慢收紧——这样团队不会一开始就被劝退。
核心思路:Lint 和 Detekt 一个侧重 Android 原生规范,一个侧重 Kotlin 代码风格。它们的配置方式完全不同,但目标一致——让规则适配项目,而不是项目去迁就规则。
4.1 Lint 的 lint.xml:简单但容易踩坑
Lint 的配置放在 lint.xml 里,通常放在模块根目录(比如 app/lint.xml)。它是 XML 格式,Android Studio 原生支持,可视化编辑也能行。但我建议手动写,因为你能控制每个规则的 severity。
我曾经遇到一个项目,lint 检查总是“不报错”,后来发现是 lint.xml 里把所有 severity 都设成了 ignore。这算是经典新手错误了。
基本结构
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<!-- 禁用某个规则 -->
<issue id="HardcodedText" severity="ignore" />
<!-- 提高某个规则的严重级别 -->
<issue id="ObsoleteSdkInt" severity="error" />
<!-- 针对特定文件路径排除 -->
<issue id="UnusedResources" severity="error">
<ignore path="**/res/values/strings.xml" />
</issue>
</lint>
issue id 对应 Lint 规则名称,可以去 官方文档(别点,这是正文,我只是提一嘴)查全列表。severity 可选值:fatal、error、warning、informational、ignore。这里有个小技巧:在 CI 里,我习惯把 fatal 和 error 一起拦截构建,warning 只输出日志不阻断。
常见场景配置表
| 目标 | 规则 ID | 推荐 severity |
|---|---|---|
| 禁止硬编码文本 | HardcodedText | error |
| 禁止过时 API 调用 | ObsoleteSdkInt | error |
| 禁止使用已弃用 API | Deprecated | warning (或 error) |
| 约束方法数量(防止超标) | MethodCount | warning |
| 忽略 R.java 中的无用资源 | UnusedResources | ignore (针对 build 文件夹) |
注意:lint.xml 里 ignore 路径用的是 Ant 风格通配符,比如 **/build/**。我曾经把 **/build/** 写成了 **/build/*,导致 build 下的子目录没被忽略,lint 跑了一个小时……嗯,血的教训。
4.2 Detekt 的 detekt.yml:从 JSON 到 YAML 的进化
Detekt 的配置在 detekt.yml 里,默认放在项目根目录或模块根目录。它是一个 YAML 文件,比 XML 可读性强太多。我刚开始接触 Detekt 时,就直接把官方默认配置复制了一份,然后逐条勾选——这方法笨但有效。
配置结构概览
# detekt.yml
build:
maxIssues: 100
excludeCorrectable: false
comments:
active: true
excludes: ["**/build/**"]
complexity:
active: true
LongParameterList:
active: true
constructorThreshold: 6
functionThreshold: 5
TooManyFunctions:
active: true
thresholdInFiles: 11
thresholdInClasses: 11
thresholdInInterfaces: 11
thresholdInObjects: 11
performance:
active: true
SpreadOperator:
active: false
potential-bugs:
active: true
UnreachableCode:
active: true
style:
active: true
WildcardImport:
active: false
MaxLineLength:
active: true
maxLineLength: 120
excludePackageStatements: true
excludeCommentStatements: true
excludeRawStrings: true
YAML 缩进不能错!空格不能少!我见过有人用 Tab 缩进导致 Detekt 直接报「配置解析失败」。记住用 2 个空格一级缩进。
关键节点说明
build:全局构建选项,maxIssues控制允许的最大问题数,超过这个数构建失败。我习惯设 200,给团队留点喘息空间,后面逐步收紧。comments:注释相关规则,比如 MissingDocumentation。我一般注释规则全关——Kotlin 代码自解释能力强,强制写文档反而拖慢开发。complexity:复杂度相关,LongParameterList、TooManyFunctions等。这是代码异味的高发区,建议保持active: true。potential-bugs:可能出 bug 的代码模式,比如UnreachableCode、DoubleNegative。这块我会开最严——一次线上 bug 的代价远超配置调优的时间。style:代码风格,比如MaxLineLength、WildcardImport。这里要结合团队规范来,我一般保留MaxLineLength: 120,把WildcardImport关掉(团队习惯用星号导入)。
配置分层:不同模块用不同规则
项目里如果有多模块(比如 app、domain、data),每个模块可以有自己的 detekt.yml。不过这样做维护成本高。我建议的做法是:项目根目录一个主配置,模块里通过 config 属性覆盖。
// 在 build.gradle.kts 或 build.gradle 中
detekt {
config = files("${project.rootDir}/detekt.yml")
// 模块级覆盖
if (project.name == "domain") {
config = files("${project.projectDir}/detekt-domain.yml")
}
}
domain 层没有 Android 依赖,可以更严格——比如 MaxLineLength: 100,NamingRules 全开。而 app 层有大量第三方库,适当放宽一些规则。
4.3 配置核心逻辑:一张图全看懂
4.4 避坑指南:我踩过的三个坑
- Lint 的 XML 编码: lint.xml 文件必须用 UTF-8 保存,否则中文注释会乱码导致解析失败。我遇到过 Jenkins 上 lint 一直报“XML parse error”,折腾半天才发现是文件保存时用了 GBK。
- Detekt 的 YAML 版本兼容: 不同 Detekt 版本对配置项的支持不一样。比如 1.22 版本里
excludeCorrectable还是boolean,到 1.23 变成了object。升级 Detekt 版本后一定要重新从官方默认配置 diff 一下。 - 不要一次性全开所有规则: 我刚开始推行 Detekt 时,把 400 多个规则全开了,结果项目编译时间多了 3 分钟,问题列表 8000+,团队直接炸毛。建议分阶段启用:先开 bug 类和复杂度类,稳定后再开风格类。
4.5 配置生效验证小技巧
配置写好了,怎么确认它生效了?有两种快速验证方式:
# 验证 Lint 配置是否生效(命令行)
./gradlew lint # 查看 lint-results.html 中规则是否按你的 severity 显示
# 验证 Detekt 配置是否生效(命令行)
./gradlew detektBaseline # 生成 baseline 文件,看排除路径是否被忽略
另外,我习惯在 CI 里加一个步骤:把 detekt.yml 和 lint.xml 的内容 print 到日志里。这样万一配置被谁改了(比如 MR 合入时带错了文件),一眼就能发现问题。
一个小技巧: 使用 detekt --print-config 可以输出实际生效的完整配置(含所有默认值),方便对比你的配置是否覆盖了期望的规则。