在 Android Studio 中使用调试程序

1. 开始之前

本 Codelab 介绍了如何在 Android Studio 中使用调试程序,以便在运行时检查“骰子应用”(Dice Roller) 中发生的情况。

调试程序是一款必不可少的工具,可用于检查为 Android 应用提供支持的代码的执行情况,以便您修复应用中的所有错误。通过调试程序,您可以指定要暂停执行代码的点,并手动与变量、方法以及代码的其他方面进行交互。

前提条件

学习内容

  • 如何将调试程序附加到 Android 应用。
  • 如何使用附加了调试程序的调试程序启动应用。
  • 如何使用调试程序的一些基本功能。
  • 调试程序通常用于什么。

所需条件

  • 安装了 Android Studio 的计算机
  • Compose 版“骰子应用”的解决方案代码

2. 观看随堂编码视频(可选)

如果您想观看课程讲师完成此 Codelab,请播放以下视频。

建议将视频展开为全屏(使用视频右下角的此图标 This symbol shows 4 corners on a square highlighted, to indicate full screen mode.)以便更清楚地查看 Android Studio 和代码。

此步骤是可选的。您也可以跳过视频,立即开始 Codelab 说明。

3. 获取入门代码

首先,下载代码

或者,您可以克隆代码的 Github 仓库

$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-dice-roller.git
$ cd basic-android-kotlin-compose-training-dice-roller

您可以在GitHub 仓库中浏览代码。

4. 运行调试程序

有两种方法可以与应用一同运行调试程序

  • 将调试程序附加到设备或模拟器上运行的现有应用进程。
  • 使用调试程序运行应用。

这两种方法在一定程度上都可以实现同样的目的。熟悉这两种方法后,您可以选择自己偏好的或所需的任何一种方法。

将调试程序附加到应用进程

如果您的应用已经在运行,您可以将调试程序附加到该应用。

要将调试程序附加到应用进程,请按以下步骤操作

  1. 点击 608818eddd06d35d.png 附加调试程序到 Android 进程

9bd4c917bad56baa.png

系统会打开一个选择进程对话框,您可以在其中选择要附加调试程序的进程。

  1. 选择 com.example.diceroller,然后点击确定

a4c65b5bc972bd46.png

Android Studio 底部会显示一个调试窗格,其中显示了一条消息,指示调试程序已附加到目标设备或模拟器。

adad34e172cbc49a.png

您已将调试程序附加到应用!不必担心这有什么意义,也不必担心如何使用调试程序,这些都将在本 Codelab 的稍后部分介绍。接下来,您将学习如何启动已附加了调试程序的应用。

使用调试程序运行应用

如果您从一开始就知道要使用调试程序,则可以在使用调试程序运行应用时节省时间。此外,如果您想调试仅在应用启动时运行的代码,则需要启动已附加了调试程序的应用。

要使用调试程序运行应用,请按以下步骤操作

  1. 调试窗格中,点击 ca283f38f21b0cb7.png 停止,然后关闭设备或模拟器上的应用。

3c82e7f80c6c174d.png

  1. 点击 67f9548b52d797b7.png 调试“app”

cbf915fde4e6b443.png

相同的调试窗格会显示在 Android Studio 底部,并带有一些控制台输出。

f69e0370c2b5ad0e.png

现在您知道如何启动调试程序了!接下来,您将学习如何使用它。

5. 使用调试程序

调试窗格

您可能注意到调试窗格顶部有很多按钮,但这些按钮目前意义不大,并且大多数呈灰显状态,无法点击。本部分将介绍调试程序中比较常用的功能。本 Codelab 将在适当的时候解释其他按钮。

首次启动调试程序时,您会在调试窗格中看到许多按钮。在调试窗格的顶部,您会看到调试程序控制台按钮。

5f35f4c555240598.png

控制台按钮显示应用的 logcat 输出。如果您在代码中有任何日志语句,当代码执行时,就会显示相应的输出。

调试程序按钮显示三个单独的窗格,这些窗格目前是空的,因为您尚未使用调试程序

  1. 帧显示
  2. 评估和观察表达式条目
  3. 变量窗格

3752c14cdd27b8c4.png

使用常用调试程序功能

设置断点

调试程序的主要功能之一是,它可让您使用断点在特定的代码行上停止执行。

要在 Android Studio 中设置断点,您需要导航到特定的代码行,然后点击行号旁边的空白处。要取消设置断点,您需要点击空白处现有的断点,使其消失。

  • 要亲自尝试,请在设置 imageResource 变量的位置设置断点。

Add and remove a breakpoint

使用“继续程序”按钮

在上一部分中,您在设置 imageResource 变量的位置设置了断点。此断点会导致在此指令处暂停执行。使用调试程序暂停执行代码后,您可能需要继续执行以继续运行应用。最直接的方法是使用继续程序按钮。

要继续程序,请按以下步骤操作

  1. 点击 67f9548b52d797b7.png 调试“app”。应用启动后,您应该会看到类似下图所示的内容

c8a1660c4209458c.png

在继续程序之前,请务必解释一下当调试程序暂停执行时您在屏幕上看到的一些内容

  • 调试窗格中的许多按钮现在可以点击了。
  • 窗格会显示许多信息,其中包括指向设置了断点的行的突出显示的引用。
  • 变量窗格会显示许多项,但此应用没有太多变量,因此目前在本 Codelab 的范围内没有很多相关信息。然而,检查变量的能力是调试程序的一项基本功能,因为它能深入了解代码在运行时发生的情况。本 Codelab 稍后将详细介绍如何检查变量。

如果您查看设备或模拟器上的应用,您会注意到屏幕是空白的,因为应用在代码行上被暂停了。更具体地说,执行已在断点处停止,并且界面尚未渲染。

请注意,应用并非总是仅仅因为设置了断点就会立即停止。这取决于您在代码中放置断点的位置。在本例中,您将其放置在应用启动时执行的行上。

要记住的关键一点是,应用仅在尝试执行设置了断点的行时才会在断点处暂停。有多种方法可以使调试程序继续执行,但现在您将使用继续程序按钮。

  1. 点击 937f070d95764107.png 继续程序

7d664cd5dd8a2d9b.png

您现在应该会看到类似下图所示的内容

388c58b0f31f797e.png

大多数信息会消失,按钮再次无法点击。应用在您的设备或模拟器上也正常显示。原因在于代码不再在断点处暂停,应用处于正常运行状态。调试程序已附加,但除非尝试执行设置了断点的代码行,否则它不会执行太多操作。保留此断点,因为在以下示例中很有用。

使用“单步进入”按钮

调试程序的单步进入按钮是一种方便的方式,可以在运行时深入查看代码。如果某条指令调用了某个方法或另一段代码,您可以使用单步进入按钮进入该代码,而无需在启动调试程序设置断点之前手动导航到该位置。

要使用单步进入按钮,请按以下步骤操作

  1. MainActivity 类的 onCreate() 函数的 setContent lambda 主体中设置断点,该断点位于调用 DiceRollerApp() 函数的位置。

aa4337eabccc85d.png

  1. 点击 67f9548b52d797b7.png 调试“app”以使用调试程序重新运行应用。执行会在调用 DiceRollerApp() 函数的行处暂停。
  2. 点击 1e7236e85d113e8f.png 单步进入

73a80d2b10caea5f.png

现在第 40 行突出显示,调试窗格中的窗格指示代码在第 40 行暂停。

ece32a03703a0531.png

如果您展开窗格,您可以看到突出显示的行之后的行以 invoke: 开头,后跟一个行号,在上一张图像中是 32。这称为调用堆栈。本质上,它显示了导致代码执行到当前行的调用链。在这种情况下,第 32 行包含调用 DiceRollerApp() 函数的指令。

当调试程序停在该函数调用上设置的断点处时,您点击了单步进入按钮,调试程序就单步进入了该函数,这使得执行到达声明该函数的第 40 行。突出显示的行表示执行暂停的位置。如果突出显示的行之后的行有相关的行号,则表明了执行路径。在此特定情况下,调试程序指示第 32 行的指令将您带到了第 40 行。

  1. 点击 937f070d95764107.png 继续程序

这应该会将您带到您设置的原始断点。您可能会对第一个示例中停止执行时看到的内容有更多的了解。这是继续程序部分第六步中的同一张图片

76a1bef8e6cdf656.png

在调用堆栈中,您可以看到 DiceWithButtonAndImage() 函数在第 50 行暂停,并且该函数是从 DiceRollerApp() 函数的第 41 行调用的,而 DiceRollerApp() 函数是在第 32 行调用的。调用堆栈功能可以帮助您了解执行路径。当一个函数在应用的许多不同位置被调用时,这非常有用。

单步进入按钮提供了一种进入函数并暂停执行而无需在该函数本身设置断点的方法。在此示例中,您在对 DiceRollerApp() 函数的调用上设置了断点。当您点击单步进入按钮时,执行会在 DiceRollerApp() 函数中暂停。

“骰子应用”是一个相当小的应用,因为没有多少文件、类或函数。当您处理更大的应用时,调试程序的单步进入功能会更加有用,因为它让您可以深入研究代码,而无需自己导航代码。

使用“单步跳过”按钮

单步跳过按钮提供了另一种在运行时单步执行应用代码的方法。它将执行移动到下一行代码并推进调试程序。

要使用单步跳过按钮,请按以下步骤操作

  • 点击 21e306488908a0f3.png 单步跳过

25b1ea30948cfc31.png

您现在可以看到,调试程序在下一行执行处(即第 51 行)暂停了代码。您可以继续按顺序单步执行每一行。

17e5998c76809c62.png

使用“单步跳出”按钮

单步跳出按钮与单步进入按钮的作用相反。单步跳出按钮不是深入到调用堆栈中,而是导航到调用堆栈的上一层。

要使用单步跳出按钮,请按以下步骤操作

  1. 点击 fbe8baec2ab73e94.png 单步跳出

您能猜到程序会在哪一行暂停吗?

9e7ce3969c28f091.png

  1. 请注意,调试程序已跳出 DiceRollerApp() 函数,并返回到调用它的那一行。

fd19d30216463877.png

当您发现自己在方法调用堆栈中处于过深的位置时,单步跳出按钮是一个有用的工具。它可让您在调用堆栈中向上移动,而无需单步执行您已进入的每个方法的所有代码。

检查变量

在本 Codelab 的前面部分,简要介绍了变量窗格,本部分将更深入地解释如何检查窗格中显示的变量,以帮助您调试应用中的问题。

要检查变量,请按以下步骤操作

  1. 点击断点,将其从调用 DiceRollerApp() 函数的位置移除,但保留设置 imageResource 变量位置的断点。
  2. 点击 67f9548b52d797b7.png 调试“app”。您应该会看到 result$delegate 变量是一个值为 1 的 MutableState。这是因为在定义该变量时,它是使用 mutableStateOf 1 实例化的。MutableState 表示 result 变量持有一个可以更改的状态。

ac37c7436b5235c0.png

  1. 点击 937f070d95764107.png 继续程序
  2. 在应用中,点击掷骰子。您的代码会再次在断点处暂停,您可能会看到 result$delegate 变量的不同值。

在此图像中,result$delegate 变量的可变状态持有值为 2。这演示了如何在运行时使用调试程序检查变量。在功能更完善的应用中,变量的值可能会导致崩溃。当您使用调试程序检查变量时,您可以更深入地了解崩溃的详细信息,以便修复错误。

a869ec4ba3b66fbf.png

6. 总结

恭喜!您已在 Android Studio 中使用过调试程序。

摘要

  • 将调试程序附加到应用。
  • 启动已附加了调试程序的应用。
  • 熟悉调试程序窗格。
  • 设置断点。
  • 从调试程序继续程序。
  • 使用单步进入按钮。
  • 使用单步跳过按钮。
  • 使用单步跳出按钮。
  • 使用调试程序检查变量。