1. 准备工作
在此 Codelab 中,您将学习如何使用 Android Studio 中的调试程序来检查 Dice Roller 应用在运行时会发生什么。
调试程序是一个重要的工具,可让您检查为 Android 应用提供支持的代码的执行情况,以便修复其中的所有 bug。借助该工具,您可以指定何时暂停代码执行,并与变量、方法和代码的其他方面进行手动交互。
前提条件
- 基本熟悉 Android Studio
- 能够在 Android Studio 中创建和运行基本 Jetpack Compose 应用
- 完成“创建交互式 Dice Roller 应用”Codelab
学习内容
- 如何将调试程序连接到 Android 应用。
- 如何在连接了调试程序的情况下启动应用。
- 如何使用调试程序的一些基本功能。
- 调试程序通常有什么用途。
所需条件
- 一台安装了 Android Studio 的计算机
- Compose 中 Dice Roller 应用的解决方案代码
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. 运行调试器
您可以通过以下两种方式将调试程序与应用一起运行:
- 将调试程序连接到在设备或模拟器上运行的现有应用进程。
- 在连接了调试程序的情况下运行应用。
无论采用哪种方式,均可在一定程度上实现相同的效果。熟悉这两种方式后,您可以选择您喜欢的方法,也可以视需要选择任一方法。
将调试程序连接到应用进程
如果您的应用已在运行,您可以将调试程序连接到该应用。
如需将调试程序连接到应用进程,请按以下步骤操作:
- 点击 Attach Debugger to Android Process。
此时将打开 Choose Process 对话框,您可以从中选择要将调试程序连接到的进程。
- 选择
com.example.diceroller
,然后点击 OK。
Android Studio 底部会显示 Debug 窗格,其中包含一条消息,指出调试程序已连接到目标设备或模拟器。
您已将调试程序连接到您的应用!无需担心这意味着什么,亦或是您可以使用调试程序执行哪些操作,此 Codelab 稍后将对此进行介绍。接下来,您将了解如何启动连接了调试程序的应用。
在连接了调试程序的情况下运行应用
如果您从一开始就确定要使用调试程序,可以在连接了调试程序的情况下运行应用,这样能节省一些时间。此外,如果您想调试仅在应用启动时才运行的代码,则需要在连接了调试程序的情况下启动应用。
如需在连接了调试程序的情况下运行应用,请按以下步骤操作:
- 在 Debug 窗格中,点击 Stop,然后在设备或模拟器上关闭应用。
- 点击 Debug 'app'。
Android Studio 底部也显示相同的 Debug 窗格,其中包含一些控制台输出。
现在,您已了解如何启动调试程序!接下来,您将了解如何使用调试程序。
5. 使用调试程序
Debug 窗格
您可能已经注意到,Debug 窗格顶部有不少按钮,但这些按钮现在意义不大,大多数按钮呈灰显状态,无法点击。本部分将介绍调试程序中的常用功能。对于其他按钮,此 Codelab 会在与所学知识相关时进行介绍。
首次启动调试程序时,您会在 Debug 窗格中看到多个按钮。在 Debug 窗格的顶部,您会看到 Debugger 和 Console 按钮。
点击 Console 按钮会显示应用的 logcat 输出。如果您的代码中有任何日志语句,则输出会在执行这段代码时显示。
点击 Debugger 按钮会显示三个单独的窗格,这些窗格目前是空的,因为您未使用调试程序:
- Frames 显示
- 求值和监视表达式条目
- “Variables”窗格
使用常用的调试程序功能
设置断点
调试程序的一个主要功能是,可让您使用断点让特定代码行停止执行。
如需在 Android Studio 中设置断点,您需要进入特定代码行,然后点击行号旁边的间距区域。如需取消设置某个断点,您需要点击间距区域中的现有断点以使其消失。
- 如需自行尝试,请在设置
imageResource
变量的位置设置一个断点。
使用“Resume Program”按钮
在上一部分中,您在设置 imageResource
变量的位置设置了一个断点。该断点会导致执行在遇到此指令时暂停。使用调试程序暂停代码执行后,您可能需要继续执行,以便继续运行应用。为此,最直接的方法就是使用 Resume Program 按钮。
如需让程序继续运行,请按以下步骤操作:
- 点击 Debug 'app'。应用启动后,您应该会看到如下图所示的内容:
在让程序继续运行之前,我们有必要对调试程序暂停执行时屏幕上显示的一些内容加以说明:
- 现在,Debug 窗格中的许多按钮都是可点击的。
- Frames 窗格会显示大量信息,其中会突出显示对设置了断点的代码行的引用。
- Variables 窗格会显示许多项,但此应用的变量并不多,因此目前没有大量在此 Codelab 讨论范围内的相关信息。但是,检查变量是调试程序的一项重要功能,因为它可以反映代码在运行时发生的情况。稍后,此 Codelab 会详细介绍如何检查变量。
如果您在设备或模拟器上查看应用,就会发现屏幕是空白的,因为应用在一行代码处暂停运行了。更具体地说,就是执行在断点处停止了,并且界面尚未呈现。
请注意,仅仅是设置了断点,并不一定能让应用立即停止运行。这取决于您在代码中放置断点的位置。在本例中,您将断点放置在了应用启动时执行的代码行中。
切记,只有在尝试执行设置了断点的代码行时,应用才会在断点处暂停运行。您可以通过多种方式让调试程序继续运行,但目前您要使用 Resume Program 按钮。
- 点击 Resume Program。
现在,您应该会看到如下图所示的内容:
大部分信息都会消失,按钮也会重新变为无法点击的状态。在您的设备或模拟器上,应用也会照常显示。这是因为代码在断点处已不再处于暂停状态,并且应用处于正常运行状态。调试程序已连接,但在尝试执行设置了断点的代码行之前,它不会执行很多操作。请保留该断点,因为它在后面的示例中有用。
使用“Step Into”按钮
借助调试程序的 Step Into 按钮,您可以非常方便地在运行时深入探究代码。如果某个指令调用了方法或其他代码段,您可以通过 Step Into 按钮进入相应代码,而无需在启动调试程序以设置断点之前手动进入相应位置。
如需使用 Step Into 按钮,请按以下步骤操作:
- 在
MainActivity
类的onCreate()
函数的setContent
lambda 正文(此处会调用DiceRollerApp()
函数)中创建一个断点。
- 点击 Debug ‘app',在连接了调试程序的情况下重新运行应用。执行会在调用
DiceRollerApp()
函数的代码行处暂停。 - 点击 Step Into。
现在,系统会突出显示第 40 行,Debug 窗格中的 Frames 窗格也会指示代码已在第 40 行暂停。
如果展开 Frames 窗格,您会看到突出显示的代码行后面的代码行以 invoke:
开头,后跟行号(在上一张图片中为“32”)。这称为“调用堆栈”。实质上,它显示的是引导代码执行到当前代码行的调用链。在本例中,第 32 行包含用于调用 DiceRollerApp()
函数的指令。
当调试程序在相应函数调用中设置的断点处停止时,如果您点击 Step Into 按钮,调试程序会步入到相应函数,这会导致系统执行到第 40 行代码(即声明该函数的位置)。突出显示的代码行指示执行暂停的位置。如果突出显示的代码行后面的各代码行有关联的行号,则表示执行路径。在本示例中,调试程序会指明第 32 行中的指令已将您带到第 40 行。
- 点击 Resume Program。
这应该会引导您前往您设置的原始断点。您或许能够进一步了解您在第一个示例中停止执行时看到的内容。下图与 Resume program 部分中第 6 步的图片相同:
在调用堆栈中,您可以看到 DiceWithButtonAndImage()
函数在第 50 行暂停执行,并且该函数是从 DiceRollerApp()
函数的第 41 行调用的,而后者是从第 32 行调用的。借助调用堆栈功能,您可以了解执行路径。如果应用中的许多不同位置都会调用某个函数,函数堆栈非常有用。
借助 Step Into 按钮,您可以进入某个函数并暂停执行,而无需在函数本身内设置断点。在本例中,您是在对 DiceRollerApp()
函数的调用中设置了断点。当您点击 Step Into 按钮时,执行会在 DiceRollerApp()
函数中暂停。
Dice Roller 是一款相当小的应用,因为文件、类或函数的数量都不多。当您处理大型应用时,调试程序的 Step Into 功能会变得更加实用,因为借助该功能,您可以详细展开代码,而无需自行浏览代码。
使用“Step Over”按钮
借助 Step Over 按钮,您可以通过另一种方式在运行时逐步检查应用代码。它会将执行移至下一行代码,然后让调试程序继续执行。
如需使用 Step Over 按钮,请按以下步骤操作:
- 点击 Step Over。
现在,您会看到调试程序在执行下一代码行(即第 51 行)时暂停执行代码。您可以依次逐步检查每行代码。
使用“Step Out”按钮
Step Out 按钮的作用与 Step Into 按钮相反。Step Out 按钮用于在调用堆栈中上移,而非展开调用堆栈的细目。
如需使用 Step Out 按钮,请按以下步骤操作:
- 点击 Step Out。
您能否猜出程序会在哪个代码行暂停?
- 请注意,调试程序已退出
DiceRollerApp()
函数,并已回到调用该函数的代码行。
当您发现自己在方法调用堆栈中的位置过深时,Step Out 按钮是一个非常有用的工具。借助该按钮,您可以在调用堆栈中逐步上移,无需逐步检查您单步进入的每个方法的所有代码。
检查变量
此 Codelab 前面的部分简要介绍了 Variables 窗格,该窗格更深入地说明了如何检查其中所示的变量,帮助您调试应用中的问题。
如需检查变量,请按以下步骤操作:
- 点击断点以将其从调用
DiceRollerApp()
函数的位置移除,但应将断点保留在设置imageResource
变量的位置。 - 点击 Debug 'app'。您应该会看到,
result$delegate
变量处于MutableState
并且值为 1。这是因为,在定义该变量时,系统将其实例化为值为 1 的mutableStateOf
。MutableState
表示结果变量具有可以更改的状态。
- 点击 Resume Program。
- 在应用中,点击 Roll。您的代码将再次在断点处暂停,并且您可能会看到
result$delegate
变量变为其他值。
在此图中,result$delegate
变量的可变状态值为 2,演示了如何在运行时使用调试程序检查变量。在功能更齐全的应用中,变量的值可能会导致崩溃。使用调试程序检查变量时,您可以更深入地了解崩溃详情,从而修复 bug。
6. 总结
恭喜!您使用了 Android Studio 中的调试程序。
总结
- 将调试程序连接到应用。
- 在连接了调试程序的情况下启动应用。
- 熟悉调试程序窗格。
- 设置断点。
- 从调试程序继续运行程序。
- 使用 Step Into 按钮。
- 使用 Step Over 按钮。
- 使用 Step Out 按钮。
- 使用调试程序检查变量。