[Android翻译]在Android Studio中调试

1,759 阅读12分钟

在Android上更快压制bug的技巧和窍门

原文地址:medium.com/androiddeve…

原文作者:medium.com/@adt_dherma…

发布时间:2020年6月13日-11分钟阅读

作为开发者,我们都知道,有些时候我们在调试器中花费的时间比在代码编辑器中花费的时间还要多。考虑到这一点,我最近借此机会看看我们Android Studio团队的成员有什么技巧和提示来加快调试速度。我已经收集了一些最好的,我认为可以节省你的时间,并且很容易融入到你的调试流程中。

虽然你的应用很可能与我们在这里使用的假设的游戏应用示例有很大不同,但这些调试技巧将适用于任何应用。

如果你想看现场演示,你可以在YouTube上找到本文的视频版本。

日志过滤和折叠

我先说说那个调试经典的小技巧:printf语句。拿一个游戏来说,每秒钟都会记录它的每秒帧率,以及每场游戏结束时用户的最终得分。在Logcat窗口中,这就会得到。

在输出中,有不少你可能不关心的信息,比如日期和线程ID。你可以很容易地配置显示的内容。在 logcat 工具栏上,点击设置图标,在配置 Logcat 标头对话框中,取消选择你不想看到的信息。

现在你可以得到更干净、更相关的日志输出,就像这样。

然而,这仍然留下了很多杂乱的信息,遮挡了高分信息。要关注这些消息,可以使用logcat搜索。在搜索中输入部分调试信息来过滤logcat窗口。

如果这是一个您经常使用的搜索,您可以通过从编辑过滤器配置中添加自定义过滤器来保存它。

然后,添加你的过滤器的细节。

另一种减少日志杂乱的方法是使用折线功能,该功能可对相似的行进行分组和折叠。从日志项目中选择一些文本,右键单击,然后选择像这样折叠行。

控制台对话框打开后,点击确定,包含所选文字的类似消息就会被折叠。

如果你以后需要查看这些信息,你可以点击线条来展开它们。还有一些沟槽把手,可以让你展开和折叠折叠的行。

连接调试器

您通常使用 "调试 "按钮或菜单选项启动调试会话。但是,如果您通过运行应用程序启动应用程序,您可以将调试器附加到正在运行的应用程序,而无需重新启动它。要做到这一点,请点击将调试器附加到Android进程。

在 "Choose Process "对话框中,高亮显示你要附加调试器的进程,然后单击 "OK"。现在,你将开始像在调试会话中一样点击断点。

移动断点

如果你发现你在一个不合适的地方设置了断点,与其清除和重置断点,不如把它拖到你关心的线上。这很有用,因为它保留了断点上的设置,包括我接下来要提到的东西。

条件断点

您可能需要追寻一个与您的应用程序或游戏中的特定类型事件有关的错误。例如,在您正在开发的游戏中,您可能希望在玩家与耗尽其最后一点健康值的对象发生碰撞时停止。您对碰撞设置了一个断点,但现在代码在每次碰撞时都会停止。为了避免这种情况,你可以设置一个有条件的断点。

要设置一个有条件的断点,右键点击一个断点并添加一个条件。条件可以是任何相当于布尔值的代码表达式。当代码打行时,如果表达式评估为真,断点就会激活。

这里,在逻辑中,当玩家刚要与对象碰撞时,设置一个条件 player.health == 1,可以让你抓住玩家最后一次与对象碰撞时,健康值降到0之前。

独立断点

一个应用程序的代码可以从许多不同的路径触发,这并不罕见。如果你有一个只沿着一个特定路径发生的错误,在代码中设置一个断点可能会导致很多不必要的中断。为了解决这个问题,你可以使用依赖性断点,只有在另一个指定的断点被击中后才会触发。例如,你可以创建一个只在你关心的路径中触发的断点,然后将其作为依赖点,这样你的其他断点就只在你感兴趣的路径中触发。

要设置一个依赖性断点,右键单击第二个断点并打开 "更多 "菜单。在 "禁用直到断点被击中 "中,选择你想要依赖的断点。

你会发现,断点图标会发生变化。

现在,你只有在前一个断点被击中后才会在这里停止。

您也可以在其他地方有条件断点,但又想避免将该条件复制粘贴到新的位置时使用此功能。

暂停线程

如果你正在调试一个多线程应用程序,你会注意到,默认情况下,断点会暂停所有线程。然而,您可能不希望出现这种行为。例如,也许您想验证您可以在一个线程上进行阻塞,而应用程序的其余部分仍然可以工作,或者您希望您的UI在调查后台任务时继续渲染。 要只暂停当前线程,请打开断点选项并在暂停设置中选择线程。

评价和记录

有时,你想看到一些与应用程序状态相关的信息,而不是停留在断点上。你可能会在代码中添加printlns来实现这个目的。与其使用这种需要重新编译的方法,你可以使用断点本身来评估和记录。

要做到这一点,在断点选项中禁用Suspend,启用Evaluate和log。

现在你可以添加任何代码表达式,它将被评估并记录到控制台。

如果你只是想快速验证你的断点是否被触发,而不关心具体细节,可以使用 "Breakpoint hit "消息来记录断点已经被击中。甚至还有一种快速创建这种断点的方法:只需按Shift键,然后在沟槽中点击即可。

禁用断点

如果您想快速禁用断点,而不是右键单击并取消选择 "已启用",您可以中键单击,或按Alt键(Mac上的Option)并左键单击,以切换断点的开启和关闭。

断点组

你一直在研究一个bug,创建断点,但发现自己进展甚微。于是,你转到另一个bug上工作,但很快,你开始打第一个bug的断点。然而,很快,你就开始打第一个bug的断点。打击不相关的断点会让人沮丧,并使你脱离调试流程。

您可以通过使用断点组来让您的生活变得更加轻松。

当你碰到第一个不需要的断点时,右击并打开 "更多"。现在你会看到所有断点的列表。多选与你的第一个bug相关的所有断点。

右键单击选定的断点并单击移动到组,然后创建新的。给这个组命名,也许是以你正在处理的bug命名。现在你可以轻松地切换所有的断点,点击一下就可以了。

另外,当你处理完这个BUG后,你可以使用组来删除所有的断点。

掉帧

有时候,当你在走过暂停的代码时,有可能会不小心踩到一个方法,而不是进入它。如果你运行的是Android 10或更高版本,你现在可以通过点击调试器工具栏中的Drop Frame进行回溯。

这个功能可以把你从当前的方法中拉出来,让你回到方法开始前的点,给你第二次踏入方法的机会。

这个功能不是 "时间机器"。如果你在一个长函数的中间,而它已经做了很多中间工作--例如,修改了当前类的状态--当你放下框架时,这些工作不会被撤销。

标记对象

有的时候,你想关注一个特定类实例的生命周期,就像这个例子,一个项目的hash码是@10140。

你可能会很想拿出一张纸,写下10140,这样当对象再次出现时,你就可以识别它。但是,或者,你可以右击该项目,点击标记对象,并给它打上标签。

现在,在任何一个调试窗口中,只要这个标记对象出现的地方,都有标签,很容易找到。在这里,我们把这个对象标记为 "myItem"。

这对于跟踪一个对象来说,更好的是能够在Watches窗口中看到它,即使你在一个完全不同的上下文中,该项目无法以其他方式到达。无论你在哪里,只要你碰到了断点,在Watches窗口中,在"_DebugLabel "后面添加你的标签(不用担心记住这个,它会自动完成)。

现在,您可以在Watches窗口中的任何地方跟随类项查看其状态。

您还可以将此功能与条件断点相结合。例如,您可以设置一个断点,右键单击它,并设置条件来检查标签对象。

现在,不用再踩过多个断点,直到特定的项目实例在范围内,代码会在正确的地方为你断点。

评价表达方式

虽然变量和手表窗口对监视显式值很有用,但有时你想更自由地探索你的代码,这就是评估表达式的功能所在。当你处于断点时,可以从调试器工具栏中的Evaluate expression中访问这个功能。

在 "表达式 "文本输入框中,输入任意表达式,按 "评估 "键进行评估。另外,如果你对一个对象进行评估,评估后你可以在结果部分浏览该对象。

评估表达式对话框可能以单行模式打开。您可以通过点击展开,轻松地将其扩展为多行。

现在你可以输入复杂的多行表达式。这些表达式可以包括变量和if语句等。

应用变化

当你有一个条件断点,在那里评估一个表达式时,即使你不停止在这个断点上,调试器仍然要进行评估。如果你在一个非常紧凑的循环中运行一些代码,例如游戏中的动画处理,这可能会导致应用程序停顿。虽然条件断点很有用,但这可能是一种边缘情况,你不能依赖它们。

绕过这个问题的一个方法是将条件表达式添加到代码中,并使用无操作表达式,这样你就可以附加断点。

做完这些后,你可能会决定重新启动你的应用程序,然后点击Debug。但是,与其这样,当运行在Android 8及以上版本时,你可以使用Apply Code Changes。

现在,你的代码已经用嵌入的表达式进行了修补。然而,你会在Frames窗口中看到你更新的方法被标记为Obsolete。

这是因为新的代码已经打了补丁,但你的调试器仍然指向旧的代码。你可以使用drop frame功能离开旧方法,进入新方法。

虽然我们在这种情况下不需要它,但还有第二个选项,Apply Changes and Restart Activity。与Apply Code Changes不同的是,这个选项也会重启活动,如果你修改了布局资源,或者你试图调试的代码是,例如在onCreate方法中,这很有用。

分析stacktrace

尽管有这些提示和技巧,但不幸的是,你的代码中可能会有bug,并收到bug报告。当你收到这些bug报告时,报告者可能已经包含了异常的堆栈的文本副本。你可以在Android Studio中使用Analyze菜单中的Analyze Stack Trace或Thread Dump将这些信息转化为有意义的信息。

这个工具提供了一个粘贴堆栈跟踪的地方,但它会自动填充你剪贴板中的任何文本。

点击 "确定",一个完整注释版的堆栈跟踪就会添加到控制台。

你可以一目了然地看到哪些是你的代码库中的代码(上面蓝色高亮显示),哪些是你可能不需要注意的代码(灰色高亮显示)。而且,你可以点击链接来快速跳转你的代码库。

最后的话

这些只是你可以用来加快调试速度的一些技巧和窍门。我们在这里没有时间去详细介绍的几个包括。

  • 在调试模式下,点击水沟中的行号,就可以运行到该行。
  • Ctrl+drag可以复制一个断点。
  • 你可以在函数的收尾括号上设置断点。
  • 你可以在字段和属性上设置断点(称为 "字段观察点")。
  • 你可以在一个接口方法上设置一个断点,使其所有的实现都中断。

还有一些与本主题相关的链接,你可能想看看,包括。