通过进行 lint 检查来改进代码

除了创建测试来确保您的应用达到其功能要求外,还务必要通过 lint 工具运行您的代码,以确保代码不存在结构问题。结构不合理的代码会影响 Android 应用的可靠性和效率,还会增加代码的维护难度,而 lint 工具有助于找到这些代码。强烈建议您先更正 lint 检测到的所有错误,然后再发布您的应用。

例如,如果 XML 资源文件包含未使用的命名空间,这样不仅占用空间,而且还需要不必要的处理。其他结构问题(例如使用目标 API 版本不支持的已废弃元素或 API 调用)可能会导致代码无法正常运行。lint 可帮助您解决这些问题。

为了进一步提高 lint 检查的性能,还应向您的代码添加注解

概览

Android Studio 提供了一个名为 lint 的代码扫描工具,可帮助您发现并更正代码结构质量方面的问题,而无需您实际执行应用,也不必编写测试用例。系统会报告该工具检测到的每个问题,并提供问题的描述消息和严重级别,以便您确定需要优先进行的关键改进。此外,您还可以降低问题的严重级别以忽略与项目无关的问题,或者提高严重级别以突出特定问题。

lint 工具可以检查您的 Android 项目源文件是否有潜在的 bug,以及在正确性、安全性、性能、易用性、无障碍性和国际化方面是否需要优化改进。使用 Android Studio 时,无论何时构建应用,都会运行配置的 lint 和 IDE 检查。不过,您也可以手动运行检查从命令行运行 lint,如本页所述。

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

  • 在编辑器窗口中查看以弹出的文本形式显示的警告和错误。lint 发现问题后,会用黄色突出显示有问题的代码。对于更严重的问题,它会在代码下面添加红色下划线。
  • 依次点击 Code > Inspect Code 后,在 lint Inspection Results 窗口中查看。

注意:在 Android Studio 中编译代码时,会运行额外的 IntelliJ 代码检查以简化代码审核。

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

lint 工具的代码扫描工作流。
图 1. lint 工具的代码扫描工作流。
应用的源文件
源文件包括组成 Android 项目的各种文件,包括 Kotlin、Java 和 XML 文件,以及图标和 ProGuard 配置文件。
lint.xml 文件
一个配置文件,可用于指定要排除的任何 lint 检查以及自定义问题严重级别。
lint 工具
一个静态代码扫描工具,您可以从命令行或在 Android Studio 中对 Android 项目运行该工具。lint 工具用于检查代码是否存在可能影响 Android 应用的质量和性能的结构问题。
lint 检查结果
您可以在控制台或 Android Studio 的 Inspection Results 窗口中查看 lint 检查结果。如果您从命令行运行 lint,结果会写入 build/ 文件夹。如需了解详情,请参阅手动运行检查部分。

从命令行运行 lint

如果您当前使用 Android Studio 或 Gradle,可以在项目的根目录下输入以下某个命令,使用 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 工具完成其检查后,会提供 XML 和 HTML 版 lint 报告的路径。然后,您可以转到 HTML 报告并在浏览器中将其打开,如图 2 所示。

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

如果您的项目包含 build 变体,lint 将仅检查默认变体。如果您想对其他变体运行 lint,则必须将该变体名称的首字母大写,并在其前面加上 lint

./gradlew lintRelease

如需详细了解如何从命令行运行 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 配置为以较低的严重级别报告非关键问题。

严重级别如下:

  • enable
  • disableignore
  • informational
  • warning
  • error
  • fatal

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

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

配置 lint 文件

您可以在 lint.xml 文件中指定 lint 检查偏好设置。如果您是手动创建此文件,请将其放置在 Android 项目的根目录下。

lint.xml 文件由封闭的 <lint> 父标记组成,此标记包含一个或多个 <issue> 子元素。lint 会为每个 <issue> 指定一个唯一的 id 属性值:

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

若要更改某个问题的严重级别或禁止对该问题进行 lint 检查,可以在 <issue> 标记中设置严重级别属性。

提示:如需查看 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 检查

您可以通过以下步骤在 Preferences 对话框中关闭 Kotlin、Java 和 XML 源文件的 lint 检查:

  1. 依次选择 File > Settings(在 Windows 上)或 Android Studio > Preferences(在 macOS 或 Linux 上)。
  2. 依次选择 Editor > Inspections
  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);

在任何可组合项上都可以实现相同的目的。以下代码段展示了如何将 off 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")

您可以使用同一注解来禁止对任何可组合函数进行 lint 检查。

配置 XML 的 lint 检查

您可以使用 tools:ignore 属性对 XML 文件的特定部分停用 lint 检查。在 lint.xml 文件中添加以下命名空间值,以便 lint 工具识别该属性:

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

以下示例展示了如何对 XML 布局文件的 <LinearLayout> 元素中的 UnusedResources 问题停用 lint 检查。如果某个父元素声明了 ignore 属性,则该元素的子元素会继承此属性。在本示例中,也会对 <TextView> 子元素停用 lint 检查:

<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"

若要禁止 lint 检查 XML 元素中的所有问题,请使用 all 关键字:

tools:ignore="all"

通过 Gradle 配置 lint 选项

通过 Android Plugin for 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 工具仅通过读取该文件来确定基准。如果要创建新基准,请手动删除该文件并再次运行 lint 以重新创建此文件。

然后,从 IDE(依次选择 Code > Inspect Code)或从命令行运行 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 检查,请依次选择 Code > Inspect Code。检查结果将显示在 Inspection Results 窗口中。

设置检查范围和配置文件

选择要分析的文件(检查范围)和要运行的检查(检查配置文件),具体操作步骤如下:

  1. Android 视图中,打开您的项目,然后选择要分析的项目、文件夹或文件。
  2. 从菜单栏中,依次选择 Code > Inspect Code
  3. Specify Inspection Scope 对话框中,查看设置。

    指定检查范围
    图 3. 查看检查范围设置。

    Specify Inspection Scope 对话框中显示的选项组合因您选择的是项目、文件夹还是文件而异:

    • 如果您选择一个项目、文件或目录,Specify Inspection Scope 对话框中会显示选定项目、文件或目录的路径。
    • 如果您选择多个项目、文件或目录,在 Specify Inspection Scope 对话框中,选定的文件旁边会显示一个选中的单选按钮。

    若要更改要检查的内容,请选中其他某个单选按钮。您可以在 Specify Inspection Scope 对话框中查看 Specify Inspection Scope 对话框中可能显示的所有字段的说明。

  4. Inspection profile 下,选择您要使用的配置文件。
  5. 点击 OK 以运行检查。

    图 4 显示了通过运行 Inspect Code 所生成的 lint 及其他 IDE 检查结果:

    选择问题以查看其解决方法。
    图 4. 检查结果。选择问题以查看其解决方法。
  6. Inspection Results 窗格中,通过展开并选择错误类别、类型或问题来查看检查结果。

    Inspection Report 窗格显示在 Inspection Results 窗格中选定的错误类别、类型或问题的检查报告,并显示错误的名称和位置。在适用情况下,检查报告会显示问题概要等其他信息,以帮助您更正问题。

  7. Inspection Results 窗格树状视图中,右键点击某个类别、类型或问题,以显示上下文菜单。

    根据上下文,您可以执行以下全部或部分操作:

    • 跳到源代码。
    • 排除和包含选定项。
    • 不显示问题。
    • 修改设置。
    • 管理检查警报。
    • 重新运行检查。

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

使用自定义范围

您可以使用 Android Studio 中提供的某个自定义范围,具体操作步骤如下:

  1. Specify Inspection Scope 对话框中,选择 Custom scope
  2. 点击 Custom scope 列表以显示选项:

    选择检查范围
    图 5. 选择要使用的自定义范围。
    • All Places:所有文件。
    • Project Files:当前项目中的所有文件。
    • Project Source Files:仅限当前项目中的源文件。
    • Project Production Files:仅限当前项目中的生产文件。
    • Project Test Files:仅限当前项目中的测试文件。
    • Scratches and Consoles:仅限您在当前项目中打开的临时文件和控制台。
    • Recently Viewed Files:仅限当前项目中最近查看过的文件。
    • Current File:仅限当前项目中的当前文件。在您选择文件或文件夹后显示。
    • Selected Directory:仅限当前项目中的当前文件夹。在您选择文件夹后显示。
    • Class Hierarchy:如果您选择此选项并点击 OK,会出现一个对话框,其中显示当前项目中的所有类。可以使用此对话框中的 Search by Name 字段过滤并选择要检查的类。如果未过滤类列表,代码检查将检查所有类。

    如果为项目配置了 VCS,您还可以选择将搜索范围限制为仅限已修改的文件。

  3. 点击 OK

创建自定义范围

如果您要检查的所选文件和目录不在当前可用的任何自定义范围内,您可以创建自定义范围:

  1. Specify Inspection Scope 对话框中,选择 Custom scope
  2. 点击 Custom Scope 列表后面的三个点。

    “Specify Inspection Scope”对话框
    图 6. “Specify Inspection Scope”对话框。

    此时将显示 Scopes 对话框。

    创建自定义范围
    图 7. 创建自定义范围。
  3. 点击对话框左上角的 按钮以定义新范围。
  4. 在随即出现的 Add Scope 列表中,选择 Local

    本地范围和共享范围均可在项目内用于 Inspect Code 功能。共享范围还可用于具有范围字段的其他项目功能。例如,当您点击 Edit Settings 图标 以更改 Find Usages 的设置时,随即出现的对话框中包含一个 Scope 字段,您可以在其中选择共享范围。

    从“Find Usages”对话框中选择共享范围
    图 8.Find Usages 对话框中选择共享范围。
  5. 为范围命名并点击 OK

    Scopes 对话框的右侧窗格填充有可用于定义自定义范围的选项。

  6. 从列表中选择 Project

    此时将显示可用项目的列表。

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

  7. 展开项目文件夹,选择要添加到自定义范围的内容,然后选择是要包含还是排除相应内容。

    定义自定义范围
    图 9. 定义自定义范围。
    • Include:包含此文件夹及其文件,但不包含其中的任何子文件夹。
    • Include Recursively:包含此文件夹及其文件,以及子文件夹及其中的文件。
    • Exclude:排除此文件夹及其文件,但不排除其中的任何子文件夹。
    • Exclude Recursively:排除此文件夹及其文件,以及子文件夹及其中的文件。

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

    自定义范围模式示例
    图 10. 自定义范围模式示例。
    • 如果您选择 java 文件夹并点击 Exclude Recursivelyjava 文件夹以及该文件夹下的所有文件夹和文件将不再用绿色突出显示。
    • 如果您选择用绿色突出显示的 MainActivity.kt 文件并点击 ExcludeMainActivity.kt 将不再用绿色突出显示,而 java 文件夹下的其他所有项目仍将用绿色突出显示。
  8. 点击 OK。自定义范围显示在列表底部。

查看和修改检查配置文件

Android Studio 具有许多 lint 及其他检查配置文件,这些配置文件可通过 Android 更新进行更新。您可以原封不动地使用这些配置文件,也可以修改它们的名称、说明、严重级别和范围。您还可以激活和禁用整组的配置文件或一组配置文件中的个别配置文件。

若要访问 Inspections 设置,请按以下步骤操作:

  1. 依次选择 File > Settings(在 Windows 上)或 Android Studio > Preferences(在 macOS 或 Linux 上)。
  2. 依次选择 Editor > Inspections
  3. Inspections 窗格列出了支持的检查及其说明。

    支持的检查及其说明
    图 11. 支持的检查及其说明。
  4. 选择 Profile 列表,以在 Default (Android Studio) 与 Project Default(活动项目)检查之间切换。

    如需了解详情,请参阅 IntelliJ 管理配置文件页面。

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

    选择一个配置文件类别后,您可以将该类别中的所有检查项目当作一个检查项目进行修改。

  6. 选择 Show Schema Actions “Show Schema Actions”图标 列表,以复制检查项目、为检查项目重命名、向检查项目添加说明以及导出/导入检查项目。
  7. 操作完成后,点击 OK