很多人在 Android Studio 里找代码检查功能时都有过这种经历:菜单栏明明写着 Analyze,进去之后却只敢点 Inspect Code,剩下那一排条目根本不知道是干什么的。还有更尴尬的——朋友说“你跑一下 inspection”,你嘴上答应着,手却停住了:Inspection 到底在哪个位置?跑完之后那一大堆结果又该怎么看?
这篇东西就是来解决这个问题的。我会从最基础的入口导航讲起,把 Inspector 相关的位置、界面、运行方式、配置逻辑和常见坑一条条拆开,覆盖从“找不到入口”到“看懂了结果但不会修”的完整过程。不管你是刚摸 Android Studio 的新手,还是已经写了几年业务代码但始终没认真用过静态检查的老手,这篇内容都值得花十分钟过一遍——因为很多团队代码质量的差距,根本不是写出来的,是查出来的。
1. 先回答“在哪里”:Inspection 入口的完整导航
先说最直接的问题。Inspection 在 Android Studio 里并不是一个独立窗口,而是分布在一组菜单项、右键动作和快捷键背后的功能集合。入口虽多,但记住主干就够了。
1.1 菜单栏的主入口:Analyze 菜单
打开任意一个项目,看顶部菜单栏,找到Analyze这一项。这个菜单在旧版本里叫 Analyze,现在的新版本依然保留了这个名字,Android Studio 没有把它改名成 Code Analysis 之类。点开后你会看到一系列条目:
- Inspect Code...
- Inspect Code in File...
- Inspect Code in Directory...
- Run Inspection by Name...
- Configure Current File Analysis...
- Code Cleanup...
其中前面三个是最常用的,分别对应“检查整个项目”“检查当前打开的文件”“检查某个指定目录”。它们的本质都是触发同一个检查引擎,只是作用范围不同。
很多人以为 Inspect Code 是唯一的入口,其实它只是最保守的那个。实际开发中,按文件、按目录、按指定检查项去跑,用的频率比全项目扫描要高得多,因为更快、结果更聚焦。
1.2 编辑器右键菜单:被忽略的快捷入口
在代码编辑区里点右键,弹出的菜单底部通常会有一栏Analyze相关操作,里面包括“Inspect Code in File”和“Run Inspection by Name”。这个入口适合那种“我改了当前这个文件,想立刻看看有没有问题”的场景。
注意一点:这个右键菜单的内容会随着你选中的元素变化。如果你选中的是一段代码、一个变量名、或者一个方法调用,部分 Analyze 选项会变成针对选中项的语义分析。如果你选了某个变量再点右键,能看到“Find Usages”“Refactor”这些都是常见的;Inspection 相关选项在大部分情况下都处于可用状态,个别场景会灰掉,比如光标停在空行时,某些针对性检查确实不可用。
1.3 快捷键:真正的高效入口
有键盘洁癖的人可以直接记快捷键。Windows/Linux 下:
- Ctrl + Alt + Shift + I:按名称运行检查项。这可能是整个 Analysis 系统里最被低估的功能,你不需要先知道检查项在哪个分类下面,只需要输入关键词,比如输入 "unused",它就能列出所有名字里带 unused 的检查,选中即可运行。
- Ctrl + Alt + Shift + Inspect(某些版本可能不存在这个组合,以你实际版本为准):全项目检查的快捷键在不同版本中并不完全固定,所以我更建议你把菜单栏路径记牢,快捷键作为辅助。
顺便提一嘴,Android Studio 的设置界面里可以自定义菜单栏快捷键。如果你经常跑全项目检查,给 Analyze -> Inspect Code 单独配一个顺手的热键,长期下来节省的时间很可观。
2. 理解了入口,还得理解它背后在做什么
找到了入口只是第一步。Inspection 这个英文词直译过来是“检查”,但它和你日常说的“编译报错”“运行崩溃”有本质区别。编译错误是硬性的、不解决就跑不起来;Inspection 是软性的、即使你不处理,代码照样能编译能运行——但它会在背后提示你潜在的问题。理解这个边界,你才不会被结果面板里一堆黄色警告吓得手足无措。
2.1 Inspection 检查的到底是什么
Android Studio 的 Inspection 体系覆盖的维度极广,常见的几大类包括:
- 代码规范与风格异常:未使用的变量、未使用的导入、多余的括号、命名不规范、魔法数字等。
- 潜在空指针与逻辑缺陷:可能为 null 的值被直接调用、数组越界风险、无效的条件判断等。
- 资源与性能问题:内存泄漏隐患、布局层级过深、频繁创建对象等。
- 框架使用错误:遗漏权限声明、错误的 Activity 启动方式、不合适的异步任务写法等。
- 兼容性问题:API 版本适配、默认 locale 环境下的显示问题等。
换句话说,Inspection 是编译器的“嘴替”——编译器和 lint 只负责那些硬性规则,而 Inspection 覆盖了更广泛的“经验性规则”。官方把这些规则打包成了一套巨大的规则库,每一条规则都定义了触发条件、检查时执行的算法、发现违规时给出的提示文本,以及建议的修复动作。
2.2 Inspection 和 Lint 到底是不是一回事
这是群里被问烂的问题。严格讲,两者不是同一个东西,但在 Android Studio 里它们经常被放在同一个操作流程里。Lint 是 Android 框架层面的静态分析工具,专注 Android 专属问题——manifest 声明、资源引用、权限、适配等;Inspection 则是 IDE 的代码分析引擎,覆盖 Java/Kotlin 语法、逻辑模式、代码风格、通用缺陷等。两者一个偏 Android 生态,一个偏语言和工程层面。
实际使用中你不需要刻意区分它们。因为Analyze -> Inspect Code 运行出来的结果里,Lint 检查项和通用检查项是混在一起展示的。你只需要知道结果面板里有一条检查项叫 Android Lint,这是 Lint 工具的产出,其余大多数条目属于 IDE 内置检查——它们是两套引擎并行工作,最后统一汇入同一个结果界面。
2.3 结果面板里的优先级是怎么定义的
每个检查项都有严重级别,这也是新手最容易忽略的点。在 Settings -> Editor -> Inspections(或者新版本里叫 Settings -> Project Settings -> Inspections)里,你可以看到所有检查项,每一项旁边都标注了严重程度:
- Error:红色,最高级别。通常表示代码在某些场景下一定会出问题,或者和编译错误强相关。不过要强调:Inspection 标 Error 不代表编译失败,它只是“以代码分析引擎的判断,这里大概率是错的”。
- Warning:黄色,中等。多数检查项默认都在这个级别,表示“有风险,建议处理”。
- Weak Warning:淡黄色。表示“可能有问题”,比如拼写错误、可简化的写法。
- Server Problem:服务端上报的问题,多用于连接远程代码分析服务的场景。
- Info:提示性信息,不影响代码质量判断,仅仅给出建议。
理解了严重级别,你就能做一件事:在结果面板里按严重级别过滤,先把 Error 级别的全部处理完,再看 Warning。如果项目里历史包袱重,Warning 上千条,不要直接开摆,善用过滤功能一条条清。
3. 真正跑一次检查:从结果面板到修复动作
入口找到了,概念理解了,接下来就该动手。这一节会把一次完整检查从“点击按钮”到“修复完成”的链路走一遍,重点说结果面板里那些一眼看不懂的东西到底是什么意思。
3.1 跑一次完整检查的参考步骤
拿一个真实的 Android 工程举例。假设我接手了一个模块,想看看整体健康度。操作顺序如下:
- 用 Android Studio 打开工程根目录,等待 Gradle 同步完成。注意:Inspection 依赖项目索引和依赖解析,如果索引没建完就跑,结果可能漏报甚至完全不准。
- 点击 Analyze -> Inspect Code。
- 弹窗里会有一个 Profile 下拉框,默认是“Default”配置;还有一个 Scope 下拉框,默认范围是整个项目。先保持默认。
- 点击 OK。IDE 底部会弹出进度条,同时系统开始扫描。扫描速度和工程大小直接相关,几万行的项目通常几十秒到几分钟。
- 扫描结束后,底部打开 Inspection Results 面板,这就是结果台账。
这个流程本身很简单,但 Note 里那个“Profile”和“Scope”值得单独多说两句——它们决定了“用什么标准查”和“查哪些代码”。
3.2 Inspection Results 面板的阅读方法
第一次打开 Inspection Results 的人很容易懵:左侧是一长串树形目录,右侧是代码片段和提示文字,底部还有一行统计。其实这个面板的结构有固定逻辑。
左侧树:按两种维度组织。默认维度是“按文件”——展开后是各个源码文件,每个文件下面是命中的检查项;你也可以切换为“按检查项”——展开后是每条检查规则,每条规则下挂着它命中的文件列表。对于直接想改代码的人,按文件更顺手;对于想系统性消灭某一类问题(比如把全项目的 unused import 清掉),按检查项更高效。
右侧区域:当你选中左侧任意一条命中记录,右侧会展示对应的代码片段。被检查项命中的那几行通常带有下划线和彩色高亮,和编辑区的波浪线颜色一致,红色对应 Error,黄色对应 Warning。
底部状态栏:显示命中问题的总数和按严重级别分布的统计。你可以点这些数字快速过滤。
还有两个高频操作按钮需要记住。一个是“Suppress”按钮——点击后会在代码里插入//noinspection注释或@SuppressLint注解,表示“这条检查我亲眼看过,确定没问题,不用再报”;另一个是“Show Source”按钮——切换是否在结果面板里同步展开编辑器的上下文,方便你一边看结果一边改代码。
3.3 能一键修复就不要手改
Inspection 最有价值的地方在于,大量的检查项不仅会告诉你“哪里有问题”,还自带修复方案。当你选中最左侧某一条命中记录时,右侧代码片段上方通常会出现一个灯泡图标,点开灯泡,会列出该检查项提供的修复动作。
比如最常见的“Unused import”检查,修复动作就是“Remove import”,你只需要点一下,IDE 自动删除这一行。再比如“Simplifiable conditional expression”这类,点灯泡之后 IDE 会提供“Simplify”选项,直接把嵌套 if 折叠成三元表达式。凡是带“Intent”标识的修复动作,说明 IDE 对这次的改动有把握,通常不会改变代码行为。
真心建议:能用灯泡修复的,一律用灯泡修复。手动删除 import、手动重命名、手动调整格式,一方面慢,另一方面容易改出错位。IDE 提供的修复合集会自动处理边界情况,比如删除 import 前会检查这个 import 是否真的没有其他被引用的符号。
3.4 Code Cleanup 是什么场景用的
Analyze 菜单里还有一个容易让人混淆的功能:Code Cleanup。它和 Inspect Code 的区别在于:Inspect Code 是“只查不改”,把所有潜在问题摸出来给你看,改不改由你决定;Code Cleanup 是“查完自动改”,它会按照你勾选的检查项,把能自动修复的问题一次性修掉。
使用方式也很简单:Analyze -> Code Cleanup,然后在弹窗里选择范围。它会先跑一遍检查,命中可自动修复的项就直接帮你改代码。适合那种拿到别人遗留代码,想快速做一轮“卫生大扫除”的场景。
这里有一个重要提醒:Code Cleanup 的自动修复不等于所有修复。它只会执行那些被标记为“可自动修复”的动作。很多需要上下文判断的检查(比如“可能存在空指针”“资源未关闭”)即使发现问题也不会自动改,因为这些改动需要开发者的判断,自动改太危险。所以用完 Code Cleanup 之后,务必再跑一次 Inspect Code,把剩下的问题单独处理。
4. 定制属于自己的 Inspection:级别、范围与分类管理
默认配置能用,但不好用。每个项目的代码风格、技术栈、历史包袱都不一样,一套默认规则不可能适配所有情况。所以真正用好 Inspection,必须学会调它的配置。这一节是全文信息密度最高的一节,建议对着软件操作。
4.1 调整检查项的严重级别
进入Settings -> Editor -> Inspections(不同版本的菜单路径可能略有差异,有的新版本集成到了 Project Settings 下,但中文界面搜“检查”也能定位)。你会看到一个长长的列表,这个列表就是整套规则库的目录树。
每条规则前面都有一个圆形图标,颜色代表当前严重级别。想改级别,选中条目后用右侧的“Severity”下拉框修改;下拉框下面还有一组选项专门控制“如何报告”。举个例子,把某个检查从 Warning 改成 Error,那么后续代码里只要命中它,编辑器里显示的就是红色波浪线,全项目检查结果里也会归入 Error 一档。
动手建议:
- 不推荐的检查项改成 Error:比如
Unused declaration。为什么不推荐?因为未使用的方法和变量通常意味着代码冗余,而冗余是后续维护最大的隐性成本之一。把这条升级成 Error,等于是强制自己在提交代码前清理垃圾。 - 拿不准的检查项调成 Weak Warning:比如很多关于潜在空指针的检查,在一些老项目里命中率极高,但项目本身经验证运行稳定,这类检查可以压低一档,避免结果面板被海量告警淹没。
- 误报严重的检查项直接关闭:比如某些场景下
Boolean method is always inverted检查会频繁误报,如果你们团队确实有“返回布尔取反”的惯例,关闭这条检查比每次手动 Suppress 省心得多。
4.2 把自己常用的规则组合保存为 Profile
默认的配置叫 Default。在 Inspections 设置页面的最上方,有一个下拉框,里面能创建新的配置方案,这玩意叫Profile。第一次用的人容易忽略它,但它才是应对多项目场景的正确姿势。
假设你同时维护两个项目:一个叫项目A,用的是老旧的 Java 代码,里面堆满了空指针隐患,你希望空指针相关的检查全部最高级暴露;另一个叫项目B,是 Kotlin 新项目,代码相对整洁,你更在意命名规范和注释完整度。这两个项目的检查策略完全不同。你可以分别建两个 Profile,一个叫“LegacyJava-Strict”,一个叫“Kotlin-Clean”,各配各的规则。跑检查时,在 Inspect Code 弹窗的 Profile 下拉框里选中对应方案即可。
创建 Profile 不需要重新选一遍所有规则。你可以先基于 Default 复制一份,再逐条修改差异项,这样最快。
4.3 Scope:不查第三方代码的正确姿势
检查范围的问题,很多人不跑一次大项目根本意识不到。默认的“Whole project”范围,会把你项目里所有源代码目录都扫描一遍。如果项目依赖了比较大的第三方库源码——比如某些库里直接把源码打进了工程,或者你们自己引用了某个大型开源项目的代码——那么检查结果里会混入大量不属于你们团队维护的代码告警。
这类告警既无法修复,也扰乱注意力。解决办法就是在检查前配置好 Scope:
在 Inspect Code 弹窗的 Scope 下拉框里,可以选择“Project Files”,这个选项通常已经帮你排除掉了 Gradle 脚本和 build 目录;更精细的还可以点击弹窗里的三个点自定义 Scope,比如把xxx/generated排除、把xxx/thirdparty排除。
我的习惯是:新建一个名为“My-Source-Code”的 Scope,把src/main/java(或src/main/kotlin)和src/test、src/androidTest加进去,其他目录统统排除。跑出来的结果 100% 是自己团队写的代码,每一行都值得看。
4.4 按名称运行指定检查项
这里想把Run Inspection by Name单独拎出来再夸一次。这个功能的入口在 Analyze 菜单下,也可以按Ctrl + Alt + Shift + I触发。它的用途是:当你明确知道要找某一条检查时,不用跑全量检查,直接搜索这条检查的名字,只针对它进行全项目扫描。
比如我想检查全项目里所有.printStackTrace()的调用位置,因为这类调用在生产环境是日志噪音。我只需要搜索“printStackTrace”,选中对应的检查项,然后选择扫描范围即可。这种针对性扫描最大的好处是快——只跑一条规则,比跑几百条规则快得多。
5. 实操中的常见问题和排查链路
跑检查这件事,看起来简单,但实际操作中几乎所有人都踩过下面这些坑。这一节的每个问题都是我遇到过的,我把完整的排查链路写出来,你遇到类似情况的时候对照着做就行。
5.1 检查结果和编辑器波浪线不一致
你可能会遇到这种情况:编辑器里明明标红了,打开 Inspection Results 面板却发现没有这条记录;或者反过来,面板里报了很多问题,编辑器里却不显示。
这个现象多数是索引缓存不同步导致的。Inspection 基于 IDE 的代码索引运行,索引在后台自动更新,但如果你改了一堆文件后立刻跑检查,索引可能还没跟上。解决方式按步来:
- 先等 Gradle 同步和索引完成。看底部状态栏,如果显示“Indexing…”之类的提示,就等它转完。
- 执行一次
File -> Invalidate Caches...里的“Invalidate and Restart”,让 IDE 彻底重建索引。 - 如果还是不一致,检查你是否用了多个 Profile。不同 Profile 之间的严重级别设置不同,编辑器默认显示的是“当前激活 Profile”的结果,检查面板却可能跑的是另一个 Profile。
前两步能解决 95% 的问题。第三步是最容易忽略的——很多人设置里改了规则级别后以为全局生效了,结果编辑器显示和跑检查的结果对不上,其实就是因为当前激活的 Profile 没有同步修改。
5.2 检查跑得太慢怎么办
中大型项目跑一次全量检查动辄几分钟,体感很差。排查链路如下:
- 确认 Scope 是否包含了第三方源码。这是最大的时间杀手。
- 确认是否选择了太多规则。如果只是开发过程中想快速查一下空指针,没必要全量跑几百条规则,用
Run Inspection by Name针对性扫描即可。 - 设置面板里调整
IDE Analysis选项。在 Settings -> Editor -> General 下,有一个 “Highlight on hover” 之类的选项,但它影响的是编辑器的实时分析,不影响手动检查。真正影响手动检查速度的,是分配给 IDE 的内存大小——如果你给 Android Studio 分的内存只有 2GB,跑大工程肯定会卡。建议 4GB 起步,具体在Help -> Change Memory Settings里调整。 - 最后一次尝试:把不需要参与检查的目录(比如
build、.gradle、generated)显式排除到检查范围之外。
5.3 误报怎么处理
总有一些检查项,适合绝大多数项目,但偏偏不适合你的项目。比如某个 Kotlin 项目里,团队约定所有工具类方法都不标记@Deprecated,而是用自定义注解标记。那么 IDE 自带的 “Deprecated API usage” 检查就会把自定义注解视为异常,疯狂误报。
处理方式有主次之分:
- 首选:调整检查项的设置。有些检查项在设置面板里提供了自定义选项。比如 “Spell checker” 可以配置词典; “No hard-coded string literals” 可以排除指定资源名。
- 次选:调低该检查项的严重级别,把误报降成 Info,或者直接取消勾选。
- 最后:针对单条代码用 Suppress 注释。如果你确认某一行代码确实不在团队规范范围内,点击结果面板里的 Suppress 按钮,它会自动在当前行上方插入
//noinspection注释,并说明原因。
千万不要因为误报多就习惯性 Suppress。Suppress 本质上是“人工确认豁免”,如果滥用,等于关闭了这套体系,后面真实的告警也会被淹没在静默里。
5.4 检查结果导不出来
有时候你想把检查结果分享给同事,但 Inspection Results 面板里找不到导出按钮。这个功能确实藏得比较隐蔽:在结果面板上方的工具条里,有一个漏斗样式旁边的“Export Inspection Results”图标,点击后可以导出为 HTML 或 XML 格式。新版 Android Studio 里也可以通过右键结果树导出。
如果导出按钮灰掉了,通常是因为检查还没执行完或者你选中的是多条混合记录。重新跑一次单文件检查,再点导出,基本能解决。
6. 从 Inspection 到团队协作:配置共享与流程沉淀
Inspection 不只是个人的代码工具,它完全可以成为团队质量基建的一部分。最后这一节聊聊怎么把个人配置变成团队规范,以及日常代码审查里 Inspection 扮演什么角色。
6.1 把 Inspection 配置纳入版本管理
Inspection 的配置实际上会被 IDE 自动保存到项目目录的.idea/inspectionProfiles/文件夹里。你手动调整过的 Profile,在保存时会同步写入这个目录。这意味着什么?意味着你可以把.idea/inspectionProfiles/提交到代码仓库里,团队其他人拉下代码后,IDE 会自动应用同一套检查方案,不需要每个人手动调一遍。
默认情况下,.idea目录整个会被加进.gitignore,包括inspectionProfiles。所以如果你想共享,需要单独把这个目录从 ignore 里放出来。具体做法是修改.gitignore,添加一行!.idea/inspectionProfiles/,然后把里面的 xml 文件提交进去。这样团队新同学拉到代码后,跑检查的规则和大家一致,代码风格和质量口径就统一了。
6.2 代码审查前先自己过一遍 Inspection
我现在做代码审查之前,一定会让提交者先跑一次受影响的文件的 Inspection。别小看这一步,它省掉了我至少一半的审查时间——因为 Inspection 能自动揪出的低级问题(未使用的 import、明显的空指针风险、命名错误、魔法数字)根本不需要人工去看。人工审查应该聚焦在架构设计、业务流程、边界条件这些机器无法判断的事情上。
如果团队协作里人人都养成了“提交前跑文件级检查”的习惯,很多 review 上的奇奇怪怪的 comment 根本不会出现。这件事不需要任何工具链改动,只需要把流程约定成文化:提交代码前,右键当前文件 -> Inspect Code in File,看到 Error 级别的问题一律清零,Warning 级别最多保留你明确解释过理由的。
6.3 从结果面板到重构清单
最后一个经验,也是我觉得 Inspection 最有价值的用法:把一次全项目检查的结果当成一份重构线索清单。很多老项目都存在“知道有问题但不知道从哪里下手”的困境。你不需要拍脑袋找重构切入点,跑一次检查,按检查项聚合,哪个类名下的 Error 最多,哪个模块命中空指针检查最密集,哪里就是重构优先级最高的地方。
我自己做模块重构之前,一定会跑一次全量检查,把结果面板里的指定检查项按文件聚合排序。那些命中最多的文件,往往就是整个项目里耦合最重、最需要被拆分的文件。这个切入点比任何架构分析工具都来得直观,因为它直接指出了“这里写坏了”。
写到这里,说几句实在话
Inspection 这套东西,我最开始也跟大多数人一样,嫌它吵,嫌它误报多,嫌它跑得慢,长期默认忽略结果面板。直到后来维护一个历史包袱很重的老模块,被线上空指针折腾过几次,才老老实实把全项目检查跑了一遍。那一遍跑完,我才发现很多问题确实早就有提示,只是当时根本没往结果面板里看一眼。
所以不管你现在处于哪个阶段,哪怕只是记住了“Analyze -> Inspect Code”这一个入口,把这个动作嵌进日常开发流程里,比看一百篇技巧文都有用。先跑起来,再慢慢调规则、配 Profile、定制 Scope——工具这种东西,用得越深,越能体会它的价值边界在哪里。