使用 lint 检查改进代码

除了 构建测试 以确保您的应用满足其功能需求外,还务必通过 lint 工具运行代码,以帮助确保您的代码没有结构问题。lint 工具有助于查找可能影响 Android 应用可靠性和效率并使代码更难维护的结构不良的代码。强烈建议您在发布应用之前更正 lint 检测到的任何错误。

例如,如果您的 XML 资源文件包含未使用的命名空间,这会占用空间并需要不必要的处理。其他结构问题,例如使用已弃用的元素或目标 API 版本不支持的 API 调用,可能会导致代码无法正确运行。Lint 可以帮助您清理这些问题。

为了提高 lint 性能,您还可以 向您的代码添加注释

概述

Android Studio 提供了一个名为 lint 的代码扫描工具,可以帮助您识别和更正代码结构质量方面的问题,而无需执行应用或编写测试用例。该工具检测到的每个问题都会附带描述消息和严重性级别,以便您可以优先处理需要进行的关键改进。您还可以降低问题的严重性级别以忽略与您的项目无关的问题,或提高严重性级别以突出显示特定问题。

lint 工具检查您的 Android 项目源文件,以查找潜在的错误和优化改进,以确保正确性、安全性、性能、可用性、可访问性和国际化。在使用 Android Studio 时,配置的 lint 和 IDE 检查会在您构建应用时运行。但是,您可以 手动运行检查从命令行运行 lint,如本页面所述。

内置的 lint 工具在您使用 Android Studio 时检查您的代码。您可以通过两种方式查看警告和错误

  • 作为编辑器窗口中的弹出文本。当 lint 发现问题时,它会以黄色突出显示有问题的代码。对于更严重的问题,它会以红色下划线标注代码。
  • 在您单击代码 > 检查代码时的 lint 检查结果窗口中。

注意:当您的代码在 Android Studio 中编译时,其他 IntelliJ 代码检查 会运行以简化代码审查。使 Android Studio 保持最新状态,以确保可以使用最新的 lint 规则和检查。

图 1 显示了 lint 工具如何处理应用源文件。

Code scanning workflow with the lint tool.
图 1. 使用 lint 工具的代码扫描工作流程。
应用源文件
源文件由构成您的 Android 项目的文件组成,包括 Kotlin、Java 和 XML 文件、图标和 ProGuard 配置文件。
lint.xml 文件
您可以使用此配置文件指定要排除的任何 lint 检查并自定义问题严重性级别。
lint 工具
一个静态代码扫描工具,您可以从命令行或在 Android Studio 中对您的 Android 项目运行。lint 工具检查可能影响 Android 应用质量和性能的结构代码问题。
lint 检查结果
您可以在控制台或 Android Studio 中的检查结果窗口中查看 lint 的结果。如果您从命令行运行 lint,则结果将写入 build/ 文件夹。有关更多详细信息,请参阅有关 手动运行检查 的部分。

从命令行运行 lint

如果您使用的是 Android Studio 或 Gradle,请使用 Gradle 包装器 通过从项目的根目录输入以下命令之一来调用项目的 lint 任务

注意:使 Android Gradle 插件 保持最新状态以使用最新的 lint 规则。

  • 在 Windows 上
    gradlew lint
    
  • 在 Linux 或 macOS 上
    ./gradlew lint
    

您应该会看到类似于以下内容的输出

> Task :app:lintDebug
Wrote HTML report to file:<path-to-project>/app/build/reports/lint-results-debug.html

当 lint 工具完成其检查后,它会提供到 lint 报告的 XML 和 HTML 版本的路径。然后,您可以导航到 HTML 报告并在浏览器中打开它,如图 2 所示。

Sample HTML lint report
图 2. 示例 HTML lint 报告。

如果您的项目包含 构建变体,lint 仅检查默认变体。如果要对其他变体运行 lint,则必须将变体名称大写并以 lint 为前缀。

./gradlew lintRelease

注意:Lint 不会自动作为构建的一部分运行。我们强烈建议您在 持续集成构建 中显式运行 lint,以便在构建现有源代码时查看最新的 lint 检查。

要了解有关从命令行运行 Gradle 任务的更多信息,请阅读 从命令行构建您的应用

使用独立工具运行 lint

如果您没有使用 Android Studio 或 Gradle,请安装 Android SDK 命令行工具 以使用独立的 lint 工具。在 android_sdk/cmdline-tools/version/bin/lint 中找到 lint 工具。

注意:如果您尝试在 Gradle 项目上运行独立工具,则会出错。您应该始终使用 gradle lint(在 Windows 上)或 ./gradlew lint(在 macOS 或 Linux 上)在 Gradle 项目上运行 lint。

要对项目目录中的一系列文件运行 lint,请使用以下命令

lint [flags] <project directory>

例如,您可以发出以下命令来扫描 myproject 目录及其子目录下的文件。问题 ID MissingPrefix 告诉 lint 仅扫描缺少 Android 命名空间前缀的 XML 属性。

lint --check MissingPrefix myproject 

要查看该工具支持的完整标志和命令行参数列表,请使用以下命令

lint --help

以下示例显示了对名为 Earthquake 的项目运行 lint 命令时的控制台输出

$ lint Earthquake

Scanning Earthquake: ...............................................................................................................................
Scanning Earthquake (Phase 2): .......
AndroidManifest.xml:23: Warning: <uses-sdk> tag appears after <application> tag [ManifestOrder]
  <uses-sdk android:minSdkVersion="7" />
  ^
AndroidManifest.xml:23: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion="?" [UsesMinSdkAttributes]
  <uses-sdk android:minSdkVersion="7" />
  ^
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources]
res: Warning: Missing density variation folders in res: drawable-xhdpi [IconMissingDensityFolder]
0 errors, 4 warnings

示例输出列出了四个警告和零个错误。

两个警告与项目的 AndroidManifest.xml 文件相关

  • ManifestOrder
  • UsesMinSdkAttributes
一个警告与 Preferences.xml 布局文件相关:UnusedResources

一个警告与 res 目录相关:IconMissingDensityFolder

配置 lint 以抑制警告

默认情况下,当您运行 lint 扫描时,该工具会检查 lint 支持的所有问题。您还可以限制 lint 要检查的问题,并且可以为问题分配严重性级别。例如,您可以抑制 lint 对与您的项目无关的特定问题的检查,并且可以配置 lint 以较低的严重性级别报告非关键问题。

严重性级别为

  • 启用
  • 禁用忽略
  • 信息
  • 警告
  • 错误
  • 严重

您可以为不同级别配置 lint 检查

  • 全局(整个项目)
  • 项目模块
  • 生产模块
  • 测试模块
  • 打开的文件
  • 类层次结构
  • 版本控制系统 (VCS) 范围

配置 lint 文件

您可以在 lint.xml 文件中指定您的 lint 检查首选项。如果您要手动创建此文件,请将其放在 Android 项目的根目录中。

lint.xml 文件包含一个包含一个或多个子 <issue> 元素的封闭 <lint> 父标记。Lint 为每个 <issue> 定义一个唯一的 id 属性值

<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <!-- list of issues to configure -->
</lint>

要更改问题的严重性级别或禁用该问题的 lint 检查,请在 <issue> 标记中设置 severity 属性。

提示:有关 lint 支持的问题及其相应问题 ID 的完整列表,请运行 lint --list 命令。

示例 lint.xml 文件

以下示例显示了 lint.xml 文件的内容

<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <!-- Disable the IconMissingDensityFolder check in this project -->
    <issue id="IconMissingDensityFolder" severity="ignore" />

    <!-- Ignore the ObsoleteLayoutParam issue in the specified files -->
    <issue id="ObsoleteLayoutParam">
        <ignore path="res/layout/activation.xml" />
        <ignore path="res/layout-xlarge/activation.xml" />
    </issue>

    <!-- Ignore the UselessLeaf issue in the specified file -->
    <issue id="UselessLeaf">
        <ignore path="res/layout/main.xml" />
    </issue>

    <!-- Change the severity of hardcoded strings to "error" -->
    <issue id="HardcodedText" severity="error" />
</lint>

此示例显示了如何报告不同问题类型。IconMissingDensityFolder 检查完全禁用,而 ObsoleteLayoutParam 检查仅在封闭的 <ignore ... /> 声明中指定的文件中禁用。

为 Kotlin、Java 和 XML 源文件配置 lint 检查

您可以在首选项对话框中关闭 Kotlin、Java 和 XML 源文件的 lint 检查

  1. 选择文件 > 设置(在 Windows 上)或Android Studio > 首选项(在 macOS 或 Linux 上)。
  2. 选择编辑器 > 检查
  3. 要禁用,请取消选择相应的源文件。

您可以通过选择相应的配置文件为 IDE 或各个项目设置这些内容。

在 Java 或 Kotlin 中配置 lint 检查

要专门为 Android 项目中的类或方法禁用 lint 检查,请将 @SuppressLint 注释添加到该代码中。

以下示例显示了如何在 onCreate 方法中关闭 NewApi 问题的 lint 检查。lint 工具将继续检查此类中其他方法的 NewApi 问题。

Kotlin

@SuppressLint("NewApi")
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

Java

@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

在任何 Composable 上都可以实现相同的功能。以下代码片段显示了如何在任何 Composable 上关闭 NewApi 检查。

Kotlin

  @SuppressLint("NewApi")
  @Composable
  fun MyComposable{
    ...
  }
  

以下示例显示了如何在 FeedProvider 类中关闭 ParserError 问题的 lint 检查

Kotlin

@SuppressLint("ParserError")
class FeedProvider : ContentProvider() {

Java

@SuppressLint("ParserError")
public class FeedProvider extends ContentProvider {

要抑制文件中的所有 lint 问题的检查,请使用 all 关键字

Kotlin

@SuppressLint("all")

Java

@SuppressLint("all")

您可以使用相同的注释来抑制任何 Composable 函数上的 lint 检查。

在 XML 中配置 lint 检查

使用 tools:ignore 属性关闭 XML 文件特定部分的 lint 检查。将以下命名空间值放入 lint.xml 文件中,以便 lint 工具识别该属性

namespace xmlns:tools="http://schemas.android.com/tools"

以下示例显示了如何在 XML 布局文件的 <LinearLayout> 元素中关闭 UnusedResources 问题的 lint 检查。ignore 属性由声明该属性的父元素的子元素继承。在此示例中,lint 检查也已禁用子 <TextView> 元素

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:ignore="UnusedResources" >

    <TextView
        android:text="@string/auto_update_prompt" />
</LinearLayout>

要禁用多个问题,请在逗号分隔的字符串中列出要禁用的问题。例如

tools:ignore="NewApi,StringFormatInvalid"

要抑制 XML 元素中所有 lint 问题的检查,请使用 all 关键字

tools:ignore="all"

使用 Gradle 配置 lint 选项

Android Gradle 插件允许您配置某些 lint 选项,例如要运行或忽略哪些检查,使用模块级 build.gradle 文件中的 lint{} 块。

以下代码片段显示了一些您可以配置的属性

Kotlin

android {
    ...
    lint {
        // Turns off checks for the issue IDs you specify.
        disable += "TypographyFractions" + "TypographyQuotes"
        // Turns on checks for the issue IDs you specify. These checks are in
        // addition to the default lint checks.
        enable += "RtlHardcoded" + "RtlCompat" + "RtlEnabled"
        // To enable checks for only a subset of issue IDs and ignore all others,
        // list the issue IDs with the 'check' property instead. This property overrides
        // any issue IDs you enable or disable using the properties above.
        checkOnly += "NewApi" + "InlinedApi"
        // If set to true, turns off analysis progress reporting by lint.
        quiet = true
        // If set to true (default), stops the build if errors are found.
        abortOnError = false
        // If set to true, lint only reports errors.
        ignoreWarnings = true
        // If set to true, lint also checks all dependencies as part of its analysis.
        // Recommended for projects consisting of an app with library dependencies.
        checkDependencies = true
    }
}
...

Groovy

android {
    ...
    lint {
        // Turns off checks for the issue IDs you specify.
        disable 'TypographyFractions','TypographyQuotes'
        // Turns on checks for the issue IDs you specify. These checks are in
        // addition to the default lint checks.
        enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
        // To enable checks for only a subset of issue IDs and ignore all others,
        // list the issue IDs with the 'check' property instead. This property overrides
        // any issue IDs you enable or disable using the properties above.
        checkOnly 'NewApi', 'InlinedApi'
        // If set to true, turns off analysis progress reporting by lint.
        quiet true
        // If set to true (default), stops the build if errors are found.
        abortOnError false
        // If set to true, lint only reports errors.
        ignoreWarnings true
        // If set to true, lint also checks all dependencies as part of its analysis.
        // Recommended for projects consisting of an app with library dependencies.
        checkDependencies true
    }
}
...

所有覆盖给定问题严重级别的 lint 方法都遵循配置顺序。例如,在finalizeDsl()中将问题设置为致命级别会覆盖在主 DSL 中禁用它的操作。

创建警告基线

您可以对项目当前的警告集进行快照,然后将该快照用作未来检查运行的基线,以便仅报告新问题。基线快照允许您开始使用 lint 使构建失败,而无需先返回并解决所有现有问题。

要创建基线快照,请修改项目的 build.gradle 文件,如下所示

Kotlin

android {
    lint {
        baseline = file("lint-baseline.xml")
    }
}

Groovy

android {
    lintOptions {
        baseline file("lint-baseline.xml")
    }
}

首次添加此行时,将创建 lint-baseline.xml 文件以建立您的基线。从那时起,工具仅读取该文件以确定基线。如果您想创建新的基线,请手动删除该文件并再次运行 lint 以重新创建它。

然后,从 IDE 中运行 lint,方法是选择代码 > 检查代码,或从命令行运行如下命令。输出将打印 lint-baseline.xml 文件的位置。您设置的文件位置可能与此处显示的不同

$ ./gradlew lintDebug -Dlint.baselines.continue=true
...
Wrote XML report to file:///app/lint-baseline.xml
Created baseline file /app/lint-baseline.xml

运行 lint 会将所有当前问题记录在 lint-baseline.xml 文件中。当前问题集称为基线。如果您想与他人共享,可以将 lint-baseline.xml 文件检入版本控制。

自定义基线

如果您只想将某些问题类型添加到基线,请通过编辑项目的 build.gradle 文件来指定要添加的问题,如下所示

Kotlin

android {
    lint {
        checkOnly += "NewApi" + "HandlerLeak"
        baseline = file("lint-baseline.xml")
    }
}

Groovy

android {
    lintOptions {
        checkOnly 'NewApi', 'HandlerLeak'
        baseline file("lint-baseline.xml")
    }
}

如果您在创建基线后向代码库中添加了任何新的警告,lint 将仅列出新引入的错误。

基线警告

在基线生效时,您会收到一条信息性警告,告知您一个或多个问题已被过滤掉,因为它们已列在基线中。此警告可帮助您记住您已配置了基线,并且需要在某个时候修复所有问题。

此信息性警告还会跟踪不再报告的问题。此信息可以让您知道是否已实际修复问题,因此您可以选择重新创建基线以防止错误在未被检测到的情况下再次出现。

注意:当您在 IDE 中以批处理模式运行检查时,基线处于启用状态,但在您编辑文件时在后台运行的编辑器内检查中将忽略它们。这是因为基线适用于代码库存在大量现有警告的情况,但您确实希望在触摸代码时在本地修复问题。

手动运行检查

要手动运行已配置的 lint 和其他 IDE 检查,请选择代码 > 检查代码。检查结果将显示在检查结果窗口中。

设置检查范围和配置文件

选择要分析的文件(检查范围)和要运行的检查(检查配置文件),如下所示

  1. Android视图中,打开您的项目并选择要分析的项目、文件夹或文件。
  2. 从菜单栏中,选择代码 > 检查代码
  3. 指定检查范围对话框中,查看设置。

    Review the inspection scope settings
    图 3. 查看检查范围设置。

    指定检查范围对话框中显示的选项取决于您选择的是项目、文件夹还是文件

    • 当您选择一个项目、文件或目录时,指定检查范围对话框将显示您选择的项目、文件或目录的路径。
    • 当您选择多个项目、文件或目录时,指定检查范围对话框将显示选定的文件的选中单选按钮。

    要更改要检查的内容,请选择其他单选按钮之一。有关指定检查范围对话框上所有可能字段的说明,请参阅指定检查范围对话框

  4. 检查配置文件下,选择要使用的配置文件。
  5. 单击确定以运行检查。

    图 4 显示了检查代码运行生成的 lint 和其他 IDE 检查结果

    Select an issue to see its resolution.
    图 4. 检查结果。选择一个问题以查看解决方案。
  6. 检查结果窗格中,通过展开和选择错误类别、类型或问题来查看检查结果。

    检查报告窗格显示检查结果窗格中选择的错误类别、类型或问题的检查报告,并显示错误的名称和位置。在适用的情况下,检查报告将显示其他信息(例如问题概要),以帮助您更正问题。

  7. 检查结果窗格树视图中,右键单击类别、类型或问题以显示上下文菜单。

    根据上下文,您可以

    • 跳转到源代码。
    • 排除和包含选定的项目。
    • 抑制问题。
    • 编辑设置。
    • 管理检查警报。
    • 重新运行检查。

有关工具栏按钮、上下文菜单项和检查报告字段的说明,请参阅检查结果工具窗口

使用自定义范围

使用 Android Studio 中提供的自定义范围之一,如下所示

  1. 指定检查范围对话框中,选择自定义范围
  2. 单击自定义范围列表以显示您的选项

    Choose Inspection Scope you want to use
    图 5. 选择要使用的自定义范围。
    • 所有位置:所有文件。
    • 项目文件:当前项目中的所有文件。
    • 项目源文件:仅当前项目中的源文件。
    • 项目生产文件:仅当前项目中的生产文件。
    • 项目测试文件:仅当前项目中的测试文件。
    • 草稿和控制台:仅当前项目中打开的草稿文件和控制台。
    • 最近查看的文件:仅当前项目中最近查看的文件。
    • 当前文件:仅当前项目中的当前文件。当您选择文件或文件夹时出现。
    • 选定的目录:仅当前项目中的当前文件夹。当您选择文件夹时出现。
    • 类层次结构:当您选择此选项并单击确定时,将出现一个包含当前项目中所有类的对话框。在对话框中,使用按名称搜索字段过滤和选择要检查的类。如果您不筛选类列表,代码检查将检查所有类。
  3. 如果您为项目配置了 VCS,则还可以选择将搜索限制为仅修改过的文件。

  4. 单击确定。

创建自定义范围

当您想要检查任何可用自定义范围未涵盖的文件和目录的选择时,您可以创建自定义范围

  1. 指定检查范围对话框中,选择自定义范围
  2. 单击自定义范围列表后的三个点。

    Specify Inspection Scope dialog
    图 6. 指定检查范围对话框。

    范围对话框将出现。

    Create a custom scope
    图 7. 创建自定义范围。
  3. 单击对话框左上角的按钮以定义新范围。
  4. 在出现的添加范围列表中,选择本地

    本地范围和共享范围都用于项目中的检查代码功能。共享范围还可以与具有范围字段的其他项目功能一起使用。例如,当您单击编辑设置以更改查找用法的设置时,结果对话框将具有范围字段,您可以在其中选择共享范围。

    Select a shared scope from the Find Usages dialog
    图 8.查找用法对话框中选择共享范围。
  5. 为范围命名并单击确定

    范围对话框的右侧窗格将填充选项,使您可以定义自定义范围。

  6. 从列表中,选择项目

    将显示可用项目的列表。

    注意:您可以为项目或包创建自定义范围。步骤相同。

  7. 展开项目文件夹,选择要添加到自定义范围的内容,并选择是否包含或排除它。

    Define a custom scope
    图 9. 定义自定义范围。
    • 包含:包含此文件夹及其文件,但不包含任何子文件夹。
    • 递归包含:包含此文件夹及其文件以及其子文件夹及其文件。
    • 排除:排除此文件夹及其文件,但不排除任何子文件夹。
    • 递归排除:排除此文件夹及其文件以及其子文件夹及其文件。

    图 10 显示main文件夹已包含,并且javares文件夹已递归包含。蓝色表示部分包含的文件夹,绿色表示递归包含的文件夹和文件。

    Example pattern for a custom scope
    图 10. 自定义范围的示例模式。
    • 如果您选择java文件夹并单击递归排除,则java文件夹及其下所有文件夹和文件上的绿色突出显示将消失。
    • 如果您选择绿色突出显示的MainActivity.kt文件并单击排除,则MainActivity.kt将不再以绿色突出显示,但java文件夹下的所有其他内容仍将以绿色突出显示。
  8. 单击确定。自定义范围将出现在列表底部。

查看和编辑检查配置文件

Android Studio 有一系列 lint 和其他检查配置文件,这些配置文件通过 Android 更新进行更新。您可以按原样使用这些配置文件,也可以编辑其名称、说明、严重性和范围。您还可以激活和停用整个配置文件组或组内的单个配置文件。

要访问检查设置

  1. 选择文件 > 设置。(在 Windows 上)或Android Studio > 首选项(在 macOS 或 Linux 上)。
  2. 选择编辑器 > 检查
  3. 检查窗格显示受支持检查及其说明的列表。

    Supported inspections and their descriptions
    图 11. 受支持的检查及其说明。
  4. 选择配置文件列表可在默认(Android Studio)和项目默认(活动项目)检查之间切换。

    有关更多信息,请参阅 IntelliJ 的管理配置文件页面。

  5. 在左侧窗格的检查列表中,选择顶级配置文件类别或展开组并选择特定的配置文件。

    选择配置文件类别时,可以将该类别中的所有检查作为一个检查进行编辑。

  6. 选择显示模式操作 显示模式操作图标 列表以复制、重命名、添加检查的描述、导出和导入检查。
  7. 完成后,点击确定