小技巧 _ 在 Android Studio 调试应用,android 开发实战项目

您会发现断点的图标发生了改变:

现在,您的应用只会在前一个断点被触发后才会在此断点停止运行。
这个功能也可以用在其他使用了条件断点的地方,从而可以避免复制粘贴条件断点到新位置的操作。
挂起线程
如果您在调试一个多线程应用,您将会注意到,在默认情况下断点将会挂起所有线程,但有时您可能不希望它这样做。举例来说,您可能想要验证某个后台线程阻塞时,应用的其他功能是否能够正常工作,或者您希望了解在执行一个后台任务时,UI 能不能够持续进行渲染。
为了仅挂起当前线程,您需要打开断点选项,并且选中? Suspend ?设置中的? Thread ?选项:

Evaluate and log?(评估与记录)
有些时候,相比起在断点处停止运行,您可能更希望看到一些有关应用状态的信息。也许您会通过在代码中添加 println 语句来做到这一点,但这种方法需要重新编译应用,您其实可以利用断点本身来进行评估与记录。
为了做到这点,您需要在断点选项中禁用? Suspend ?并启用? Evaluate and log :

现在,您可以在输入框中添加任何代码表达式,相应内容会被评估并记录至控制台。
如果您只是想快速验证断点是否触发并且不在乎其中的细节信息,可以使用? "Breakpoint hit"?信息 来记录断点的触发事件。您甚至可以使用 Shift + 添加断点的方式来让这一操作变得更加快捷。
禁用断点

禁用断点 (并非删除断点),可以右键点击断点并从弹框中取消选中 Enabled 选框。您也可以通过按住 Alt (在 Mac 上是 Option) 并点击断点,从而更快速地禁用断点。
断点分组
您一定遇到过这种场景: 您正在解决一个 Bug,并为此添加了几个断点,但是发现自己一时间没什么头绪,所以您就去解决别的 Bug 了。然而,很快您就开始触发为了解决第一个 Bug 所添加的断点。触发无关的断点不但会让人困扰,还会把您带离您的调试流程。
您可以使用断点分组来让开发过程更舒心一些。
当您的程序运行到第一个与当前调试流程无关的断点时,右击并打开? More ?菜单,这时您会看到一个所有断点的列表,您可以在这里复选所有与第一个 Bug 相关的断点:

右击选中的断点,并选择? Move to group ?接下来?? Create new ?并为新的分组命名,例如以您正在处理的 Bug 命名。现在,您可以仅通过点击轻松地启用和禁用所有的断点了。

当然,您也可以在解决了 Bug 之后,使用分组功能删除所有相关的断点。
Drop frame (丢弃当前帧)
有些时候,当您浏览挂起的代码时,可能会意外跳过某个本应该进入的方法。如果您的设备运行的是 Android 10 或者更高版本,您可以通过点击调试工具栏中的? Drop Frame ?按钮来进行回溯:

这个功能会把您从当前的方法带回到其开始执行前的节点,从而给您一个重新进入该方法的机会。
此功能并不是?"时间机器"。如果您正处于一个长函数的中间位置,而它此前已经执行了许多工作 (例如,修改了当前类的状态)。在您丢弃当前帧时,这类操作所产生的改变不会被撤销。
Mark object (标记对象)
有时候,您会想要跟踪某些特定类型实例的生命周期。本例中,要跟踪的对象有一个哈希值: @10140:

为了能够在这个对象再次出现时可以认出它来,您可能已经掏出纸笔准备记下这个数字了。不过您也可以选择另一种方式: 右击该对象,点击? Mark Object ?为其添加标签。
这样一来,无论被标记的对象出现在调试窗口的任何地方,它都会带有您添加的标签以方便辨认。这里我们为该对象添加一个 " myItem "?标签:

更棒的是,就算您处于完全不同的上下文,无法触及到刚才的对象,您也可以在? Watches ?窗口对其进行查看。无论您处在什么位置,只要触发断点,就可以在? Watches ?窗口添加后缀为 " _DebugLabel "?的标签 (不用担心自己会不记得后缀的内容,这里有自动补全):

现在,您可以在任何地方使用? Watches ?窗口来观察该类型对象的状态。
您也可以将此功能与条件断点组合。举例来说,您可打一个断点,右击并为其设置一个条件来检查打了标签的对象:

这样一来,就不用在进入包含特定实例的范围之前跳过一堆断点,代码会运行到合适的地方再停止:

Evaluate expression (评估表达式)
尽管? Variables ?和? Watches ?窗口对于跟踪某个显式值时已经十分好用,但您有时候还是会想要更加自由地探索您的代码,这时候就轮到评估表达式功能登场了。当您正处于某个断点时,您可以使用调试工具栏中的? Evaluate expression ?按钮来访问这一功能。

您可以在 Expression 输入框中输入任何表达式,点击?Evaluate?按钮就可以对其进行评估。当然,如果您评估了一个对象,在评估完成后,您就可以在 Result?部分浏览该对象的详细信息:

评估表达式弹窗可能会以单行模式打开,您可以通过点击? Expand ?来将其扩展为多行模式:

现在,您可以输入复杂的多行表达式,其中可以包含变量、i
《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
f 语句等各种内容:

Apply changes
前面讲过,当您使用条件断点时,会需要评估一个表达式;即便代码没有在断点停止,调试器依然需要执行评估操作。如果您在一个非常紧密的循环中运行评估操作,例如游戏中的动画处理,则可能导致应用停顿。尽管条件断点很有用,但在某些情况下您可能无法依靠它们。
解决此问题的一种方法是将条件表达式添加到代码中,并使用无操作 (no-op) 表达式,从而使其可以附加断点:

在修改完代码之后,您可能会决定重启应用并点击? Debug ?按钮,但是如果您的应用运行在 Android 8 或更高版本的系统中,您可以使用? Apply Code Changes :

现在,嵌入的表达式已经修补了您的代码,但您仍然会在? Frames ?窗口中看到您已经更新的方法被标记为 过时 (Obsolete) :

这是因为,虽然新的代码已经打好了补丁,但是调试器指向的仍是旧的代码。您可以使用丢弃当前帧的功能来离开旧的方法,然后进入修改过的方法之中。
尽管本例中并不需要,但这里还有一种选择:? Apply Changes and Restart Activity 。不同于? Apply Code Changes ,该操作会重启 Activity。如果您修改了布局资源或您要调试的代码,例如在 onCreate 方法中,该选项将非常有用。

分析堆栈信息
就算您掌握了所有的窍门与技巧,您的代码仍然可能出现 Bug,而您也会因此收到一些崩溃报告,这些报告中则可能包含了异常堆栈信息的文本副本。您可以使用 Analyze?菜单中的?Analyze Stack Trace or Thread Dump 将这些信息转化为有意义的内容。
此工具提供了一个粘贴堆栈信息的文本框,不过它也会自动填充系统剪贴板中的文本:

点击? OK ?之后,就会将包含完整注释的堆栈信息添加到控制台:

您可以一眼看出来自您自己代码文件的内容 (以蓝色突出显示) 与您可能不需要关注的代码 (以灰色突出显示)。并且,您可以通过单击链接在您的代码文件中进行跳转。
结语
本文提供了一些可以加快调试速度的技巧和窍门。由于篇幅所限,更多技巧简单归纳如下:
在 Debug 模式下,点击代码的行数数字可以直接执行此行代码
Ctrl + 拖动操作可以复制断点
您可以在函数的右括号处设置断点
您可以在字段和属性上设置断点,被称为 "field watchpoints"
您可以为接口中的方法设置断点,从而使它的所有实现都会触发断点您可以通过下面这个视频了解更多本文的细节和演示内容:
腾讯视频链接:v.qq.com/x/page/o303…
Bilibili 视频链接: www.bilibili.com/video/av781…也请您查阅更多与本话题相关的资源:
《设计思想解读开源框架》

第一章、 热修复设计
第一节、 AOT/JIT & dexopt 与 dex2oat
第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题
第三节、热修复设计之热修复原理
第四节、Tinker 的集成与使用(自动补丁包生成)
第二章、 插件化框架设计
第一节、 Class 文件与 Dex 文件的结构解读
第二节、 Android 资源加载机制详解
第三节、 四大组件调用原理
第四节、 so 文件加载机制
第五节、 Android 系统服务实现原理
第三章、 组件化框架设计
第一节、阿里巴巴开源路由框——ARouter 原理分析
第二节、APT 编译时期自动生成代码 &动态类加载
第三节、 Java SPI 机制
第四节、 AOP&IOC
第五节、 手写组件化架构
第四章、图片加载框架
第一节、图片加载框架选型
第二节、Glide 原理分析
第三节、手写图片加载框架实战
第五章、网络访问框架设计
第一节、网络通信必备基础
第二节、OkHttp 源码解读
第三节、Retrofit 源码解析
第六章、 RXJava 响应式编程框架设计
第一节、链式调用
第二节、 扩展的观察者模式
第三节、事件变换设计
第四节、Scheduler 线程控制
第七章、 IOC 架构设计
第一节、 依赖注入与控制反转
第二节、ButterKnife 原理上篇、中篇、下篇
第三节、Dagger 架构设计核心解密
第八章、 Android 架构组件 Jetpack
第一节、 LiveData 原理
第二节、 Navigation 如何解决 tabLayout 问题
第三节、 ViewModel 如何感知 View 生命周期及内核原理
第四节、 Room 架构方式方法
第五节、 dataBinding 为什么能够支持 MVVM
第六节、 WorkManager 内核揭秘
第七节、 Lifecycles 生命周期
- 本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
评论