使用调节和测量试验,Debug调节和测验详细解释

2020-03-17 作者:网站首页   |   浏览(129)

时间: 2019-12-28阅读: 73标签: 调试

日常开发中,我们难免会遇到BUG,如何快速的定位问题,发现问题尤为重要,这直接关系到我们开发的效率;所以我们必须要快速准确的定位问题,提高开发效率,并提升自己的代码质量;接下来我们就来说一下Android Studio中的Debug调试基础和技巧,学会这些可以帮助我们高效精准的定位问题,发现问题,并解决问题;

程序调试是程序投入运行之前,使用手工或编译程序等方法进行的测试,主要用以修正语法错误和逻辑错误。程序调试是保证计算机信息系统正确性的必不可少的步骤。在Flutter应用开发中,Android Studio和VSCode是两种比较常见的集成开发环境,因此项目调试也围绕这两款IDE进行。Android Studio为Flutter提供完整的集成IDE体验,因此Android的调试技巧对于Flutter来说也是适用的。在 Flutter 中,调试代码主要分为输出日志、断点调试和布局调试 3 类,因此Flutter的调试也将围绕这 3 个主题。Android Studio

一般来说我们有两种办法调试一个debuggable的apk;其一是下好断点,然后用debug模式编译安装这个app;其二是 attach process,在Android Studio里面就是这么一个对话框:

输出日志

yzc216亚洲城 1

为了便于跟踪和记录应用的运行情况,我们在开发时通常会在一些关键步骤输出日志(Log),在Flutter中我们使用 print 函数在控制台打印出相关的上下文信息。通过这些信息,就可以定位代码中可能出现的问题。不过,由于涉及 I/O 操作,使用 print 来打印信息会消耗较多的系统资源。同时,这些输出数据很可能会暴露 App 的执行细节,所以我们在发布正式版时还需要屏蔽掉这些输出。

Paste_Image.png

不过最工程化的做法是读取项目配置文件,根据运行环境来开启日志调试功能。为了根据不同的运行环境来开启日志调试功能,我们可以使用 Flutter 提供的debugPrint 来代替 print。debugPrint 函数同样会将消息打印至控制台,但与 print 不同的是,它提供了定制打印的能力。也就是说,我们可以向 debugPrint 函数,赋值一个函数声明来自定义打印行为。

第二种方法比较常用,我们可以在启动apk之后,直接下断点,然后attach process到制定进程,条件触发之后就可以直接进入调试模式。(本篇所有示例均是在第二种方式下进行的 attach process)

比如在下面的代码中,我们将 debugPrint 函数定义为一个空函数体,这样就可以实现一键取消打印的功能了。

我们来看一下进入debug模式后的界面:

debugPrint = (String message, {int wrapWidth}) {};//空实现

yzc216亚洲城 2

在 Flutter 中,我们可以使用不同的 main 文件来表示不同环境下的入口。同样,在Flutter开发中,可以通过 main.dart 与 main-dev.dart,去分别定义生产环境与开发环境不同的打印日志行为。

Paste_Image.png

在下面的例子中,我们将生产环境的 debugPrint 定义为空实现,将开发环境的 debugPrint 定义为同步打印数据,如下所示。

android studio大体为我们提供了6个功能区:
1、单步调试区
2、断点管理区
3、求值表达式
4、线程帧栈区
5、对象变量区
6、变量观察区
下面我们分别对这6个区域进行介绍

//main.dartvoid main() { // 将debugPrint指定为空的执行体, 所以它什么也不做 debugPrint = (String message, {int wrapWidth}) {}; runApp(MyApp()); }//main-dev.dartvoid main() async { // 将debugPrint指定为同步打印数据 debugPrint = (String message, {int wrapWidth}) = debugPrintSynchronously(message, wrapWidth: wrapWidth); runApp(MyApp());}

一、单步调试区

yzc216亚洲城 3

Paste_Image.png

该区提供了调试的主要操作,主要有:Step over、step into、force step into、step out、drop frame。

可以看到,在代码实现上,我们只要将应用内所有的 print 都替换成 debugPrint,就可以满足开发环境下打日志的需求,也可以保证生产环境下应用的执行信息不会被意外打印。

1、Show Execution Point

yzc216亚洲城 4

Paste_Image.png

点击该按钮,光标将定位到当前正在调试的位置.

断点调试

2、Stem Over

yzc216亚洲城 5

Paste_Image.png

单步跳过,点击该按钮将导致程序向下执行一行。如果当前行是一个方法调用,此行调用的方法被执行完毕后再到下一行。(注意不会进入方法内部)

输出日志固然方便,但如果要想获取更为详细,或是粒度更细的上下文信息,静态调试的方式非常不方便。这时,我们需要更为灵活的动态调试方法,即断点调试。断点调试可以让代码在目标语句上暂停,让程序逐条执行后续的代码语句,来帮助我们实时关注代码执行上下文中所有变量值的详细变化过程。

3、Step Into

yzc216亚洲城 6

Paste_Image.png

单步跳入,执行该操作将导致程序向下执行一行。如果该行有自定义的方法,则进入该方法内部继续执行,需要注意如果是类库中的方法,则不会进入方法内部。

Android Studio 提供了断点调试的功能,调试 Flutter 应用与调试原生 Android 代码的方法完全一样,具体可以分为三步,即标记断点、调试应用、查看信息。

4、Force Step Into

yzc216亚洲城 7

Paste_Image.png

强制单步跳入,和step into功能类似,主要区别在于:如果当前行有任何方法,则不管该方法是我们自行定义还是类库提供的,都能跳入到方法内部继续执行

下面以 Flutter 默认的计数器应用模板为例,观察代码中 _counter 值的变化,体会断点调试的全过程。

5、Drop Frame

yzc216亚洲城 8

Paste_Image.png

中断执行,并返回到方法执行的初始点,在这个过程中该方法对应的栈帧会从栈中移除.换言之,如果该方法是被调用的,则返回到当前方法被调用处,并且所有上下文变量的值也恢复到该方法未执行时的状态。

首先是标记断点。既然我们要观察 _counter 值的变化,因此在界面上展示最新的 _counter 值时添加断点,去观察其数值变化是最理想的。因此,我们在行号右侧点击鼠标,可以把断点加载到初始化 Text 控件所示的位置。

6、Force Run to Cursor

yzc216亚洲城 9

Paste_Image.png

很好用的一个功能,可以忽略所有的断点,跳转到当前光标所在的位置调试;假如我们现在在第8行有断点,第10行有断点,目前程序停留在第8行断点上,我们将光标定位到第9行,单击该按钮,程序将跑到第9行;

在下图的例子中,我们为了观察 _counter 在等于 20 的时候是否正常,还特意设置了一个条件断点 _counter==20,这样调试器就只会在第 20 次点击计数器按钮时暂停下来。

7、Evaluate expression

yzc216亚洲城 10

Paste_Image.png

点击该按钮会在当前调试的语句处嵌入一个交互式解释器,在该解释器中,你可以执行任何你想要执行的表达式进行求值操作。假如我们当前断点处有一个result的返回值;我们单击该按钮会弹出一个对话框,在该对话框中我们可以对该result进行各种表达式操作;

添加断点后,对应的行号将会出现圆形的断点标记,并高亮显示整行代码。到此,断点就添加好了。当然,我们还可以同时添加多个断点,以便更好地观察代码的执行过程。

二、断点管理区

yzc216亚洲城 11

Paste_Image.png

接下来则是调试应用了。和之前通过点击Run 按钮的运行方式不同,这一次我们需要点击工具栏上的虫子图标,以调试模式启动 App,如下图所示。等调试器初始化好后,我们的程序就启动了。由于设置了断点,所以当代码运行到了断点位置,自动进入了 Debug 视图模式,如下图所示。

1、Return

yzc216亚洲城 12

Paste_Image.png

点击该按钮会停止目前的应用,并且重新启动.换言之,就是你想要重新调试时,可以使用该操作,嗯,就是重新来过的意思.

按照功能的不同,可以把 Debug 视图模式划分为 4 个区域,即 A 区控制调试工具、B 区步进调试工具、C 区帧调试窗口、D 区变量查看窗口。

2、Resume Program

yzc216亚洲城 13

Paste_Image.png

跳转到下一个断点处,可以理解为下一个断点;如果没有断点,则运行结束;

控制调试工具区域主要用来控制调试的执行情况,如下图所示。我们可以点击继续执行按钮来让程序继续运行、点击终止执行按钮来让程序终止运行、点击重新执行按钮来让程序重新启动,或是在程序正常执行时,点击暂停执行按钮按钮来让程序暂停运行。当然,我们可以点击编辑断点按钮来编辑断点信息,或是点击禁用断点按钮来取消断点。步进调试工具区域主要用来控制断点的步进情况,如下图所示。可以点击单步跳过按钮来让程序单步执行(但不会进入方法体内部)、点击单步进入或强制单步进入按钮让程序逐条语句执行,甚至还可以点击运行到光标处按钮让程序执行到在光标处。认为断点所在的方法体已经无需执行时,则可以点击单步跳出按钮让程序立刻执行完当前进入的方法,从而返回方法调用处的下一行。担任,还可以点击表达式计算按钮来通过赋值或表达式方式修改任意变量的值。

3、Stop

yzc216亚洲城 14

Paste_Image.png

停止调试;结束运行;

C 区用来指示当前断点所包含的函数执行堆栈,D 区则是其堆栈中的函数帧所对应的变量。

4、View BreakPoints

yzc216亚洲城 15

Paste_Image.png

单击该按钮将会进入断点管理页面,在这里你可以查看所有断点,管理或者配置断点的行为,如:删除,修改属性信息等;

布局调试

5、Mute BreakPoints

yzc216亚洲城 16

Paste_Image.png

该按钮用来禁用/启动所有断点,假如我们在某个断点处得到了我们想要的结果,并不想看其他后续断点可以点击该按钮禁用所有断点,然后程序会正常执行结束;

除了输出日志、断点调试,布局分析也是开发中不可缺少的代码优化手段。借助Flutter提供的Flutter Inspector 可视化工具,可以帮助我们诊断布局问题。打开Android Studio,然后点击工具栏上的“Open DevTools”按钮即可启动 Flutter Inspector,如下图所示。随后,Android Studio 会打开浏览器,将Flutter应用程序的的 Widget 树结构展示在面板中。可以看到,Flutter Inspector 所展示的 Widget 树结构,与代码中实现的 Widget 层次是一一对应的。除了进行布局调试外,还可以使用Flutter Inspector进行布局调优。

三、变量观察区

yzc216亚洲城 17

Paste_Image.png

我们在调试的时候,希望看某个变量的值,所以我们只需要简单设置一下就可以在变量观察区看到该变量的值,如下所示

yzc216亚洲城 18

Paste_Image.png

这里有一个技巧,如果我们在调试过程中,突然想要看看这个变量换一个值后的运行结果;可以在调试的过程中修改该变量的值,具体操作如下:

yzc216亚洲城 19

Paste_Image.png

如上图所示,右击变量num2选择set value可以弹出对话框重新设置num2的值,如下所示

yzc216亚洲城 20

Paste_Image.png

可以看出num2的值原先为10,我们修改为50,回车即可生效;

yzc216亚洲城 21

Paste_Image.png

运行结果发生变化;

上面已经介绍了单点调试、变量管理和变量观察三个区域,接下来我们根据断点的分类来介绍其他区域;

VSCode

断点的分类

断点是调试器的功能之一,可以让程序暂停在需要的地方,帮助我们进行分析程序的运行过程。
在Android Studio中,断点又被以下五类:
条件断点
日志断点
异常断点
方法断点
属性断点

除了Android Studio外,VSCode也是一款比较常见的Flutter应用程序开发工具。使用VSCode提供的图形化调试界面,开发者可以很方便的进行Flutter应用的调试工作。使用VSCode打开Flutter项目,然后点击VSCode的断点调试按钮即可开启调试,如下图所示。需要说明的是,第一次使用VSCode进行断点调试时,需要先安装并激活Dart DevTools调试工具。如果不确定是否绑定过DevTools工具,可以使用快捷键【command shift p】打开VSCode工具栏,然后输入Open DevTools打开调试窗口。然后,在需要调试的代码处设置断点,点击左上方的开启调试按钮开启调试即可。当代码运行到断点处时,就会停留在断点处,然后就可以进行相关调试操作。

1、条件断点

所谓的条件断点就是在特定条件发生的断点,也就是,我们可将某个断点设置为只对某种事件感兴趣,最典型的应用就是在列表循环中,我们希望在某特定的元素出现时暂停程序运行。假如我们有一个数组里面有1、2、3、4、5五个值,我们想在值等于3的时候停下来,可以设置条件断点;

yzc216亚洲城 22

Paste_Image.png

右击断点,在弹出的对话框中设置相应的条件即可,我们运行一下看下效果

yzc216亚洲城 23

Paste_Image.png

可以看到在num==3的时候,程序停了下来;

原文:

2、日志断点

很多时候我们调试的时候更多的是打印日志定位异常代码,缩小范围之后再使用断点解决问题;所以经常做的事情就是在代码里面添加日志信息,输出函数参数,返回信息,输出我们感兴趣的变量信息等。但是这样做的问题在于我们需要重新编译运行程序,并且添加了很多无谓的代码且不好管理,这个时候我们可以使用日志断点;该类型的断点不会使程序停下来,而是在输出我们要它输出的日志信息,然后继续执行。
举例说明:

yzc216亚洲城 24

Paste_Image.png

同样是右击断点,在上图的对话框中进行设置我们来看一下运行效果:

yzc216亚洲城 25

Paste_Image.png

是不是比你在代码中添加输出语句方便多了。

3、异常断点

在有些情况下,我们只对某些特定的异常感兴趣,或者我们只对异常感兴趣;我们希望只要程序发生异常程序就能断下来;这好像保存现场一样,这样就会留下的线索比较多,可以使我们快速的找到问题得根源;

举例说明,首先我们添加一个异常断点,单击

yzc216亚洲城 26

然后在弹出的对话框中进行如下设置

yzc216亚洲城 27

Paste_Image.png

yzc216亚洲城,假如我们只关心空指针异常可以进行如下设置

yzc216亚洲城 28

Paste_Image.png

选中空指针异常即可,我们人为设置一个空指针异常来看下运行效果:

yzc216亚洲城 29

Paste_Image.png

图中的bt_ride是一个空值的Button,可以看到,当程序发生空指针异常后会将光标直接定位的发生异常的位置;

4、方法断点

传统的调试方式是以行为单位的,所谓单步调试;但是很多时候我们关心的是某个函数的参数,返回值;(回想一下我们使用日志的时候打印的最多的信息难道不是函数的参数和返回值吗?)使用方法断点,我们可以在函数级别进行调试;如果经常跳进跳出函数或者只对某个函数的参数感兴趣,这种类型的断点非常实用。具体使用方法有两种方式;最简单的是在你感兴趣的方法头那一行打上断点,这时候你会发现断点图标有点不一样,这就是方法断点了,如下图:

yzc216亚洲城 30

Paste_Image.png

5、Field WatchPoint

有没有这样一种场景:你发现某个值莫名其妙滴不知道什么时候被谁给修改了,罪魁祸首是谁?那么我们怎么揪出这个修改我们值的捣蛋鬼呢?那就是这个 Field WatchPoint的功能了;使用它我们可以在某个Field被访问或者修改的时候让程序断下来;完美解决这个问题。我们可以直接在这个变量旁边单击就可以添加Field WatchPoint

yzc216亚洲城 31

Paste_Image.png

我们可以右击从弹出的菜单中设置默认该变量被修改的时候断下来,也可以设置每次访问该值都断下来;
好了,本篇对Android Studio中的debug调试就介绍到这里了,其实debug调试的功能远不止这些,剩下的你们可以自己去发掘,以上的这些,可以发现解决很大一部分bug了@_@

本文由yzc216亚洲城发布于网站首页,转载请注明出处:使用调节和测量试验,Debug调节和测验详细解释

关键词: yzc216亚洲城