在 Android Studio 中使用调试器

1. 开始之前

本 Codelab 教您如何在 Android Studio 中使用调试器来检查掷骰子应用在运行时发生的情况。

调试器是一个必不可少的工具,它允许您检查为 Android 应用提供支持的代码的执行情况,以便您可以修复其中的任何错误。它允许您指定代码执行挂起的点,并手动与变量、方法以及代码的其他方面进行交互。

先决条件

您将学到什么

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

您需要什么

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

2. 观看随附视频(可选)

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

建议将视频扩展到全屏(使用此图标 此符号显示一个突出显示的正方形的四个角,表示全屏模式。 在视频右下角),以便您可以更清楚地看到 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 稍后会详细介绍如何检查变量。

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

请记住,应用不会总是仅仅因为设置了断点而立即停止。这取决于你在代码中放置断点的位置。在本例中,你将其放置在应用启动时执行的一行上。

需要记住的关键点是,只有当尝试执行设置了断点的行的代码时,应用才会在断点处暂停。有多种方法可以向前移动调试器,但目前你使用的是恢复程序按钮。

  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 行调用的,而该函数又是从第 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 表示结果变量保存可以更改的状态。

ac37c7436b5235c0.png

  1. 点击 937f070d95764107.png 恢复程序
  2. 在应用中,单击**“滚动”**。您的代码再次在断点处暂停,您可能会看到 result$delegate 变量的不同值。

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

a869ec4ba3b66fbf.png

6. 结论

恭喜!您已在 Android Studio 中使用调试器。

摘要

  • 将调试器附加到应用。
  • 启动已附加调试器的应用。
  • 熟悉调试器窗格。
  • 设置断点。
  • 从调试器恢复程序。
  • 使用**“步入”** 按钮。
  • 使用**“步过”** 按钮。
  • 使用**“步出”** 按钮。
  • 使用调试器检查变量。