使用 Lint 检查改进代码

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

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

为了提高 Lint 性能,您还可以向代码添加注解

概览

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

Lint 工具会检查您的 Android 项目源文件是否存在潜在的 Bug 和优化改进,以确保正确性、安全性、性能、可用性、无障碍性和国际化。使用 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 项目上从命令行或在 Android Studio 中运行它。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 以较低的严重级别报告非关键问题。

严重级别为:

  • 启用
  • disableignore
  • 信息
  • 警告
  • 错误
  • 致命

您可以针对不同的级别配置 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> 标签中设置严重性属性。

提示:要获取 Lint 支持的所有问题及其对应问题 ID 的完整列表,请运行 lint --list 命令。--list 选项必须从独立 Lint 工具运行。

示例 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 插件允许您使用模块级 build.gradle 文件中的 lint{} 块来配置某些 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。输出将打印 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 将仅列出新引入的 Bug。

基线警告

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

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

注意:当您在 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. 完成后,点击确定