程序调试是程序投入运行以前,使用手工或编译程序等方法进行的测试,主要用以修正语法错误和逻辑错误。程序调试是保证计算机信息系统正确性的必不可少的步骤。
在Flutter应用开发中,Android Studio和VSCode是两种比较常见的集成开发环境,所以项目调试也围绕这两款IDE进行。Android Studio为Flutter提供完整的集成IDE体验,所以Android的调试技巧对于Flutter来讲也是适用的。在 Flutter 中,调试代码主要分为输出日志、断点调试和布局调试 3 类,所以Flutter的调试也将围绕这 3 个主题。浏览器
为了便于跟踪和记录应用的运行状况,咱们在开发时一般会在一些关键步骤输出日志(Log),在Flutter中咱们使用 print 函数在控制台打印出相关的上下文信息。经过这些信息,就能够定位代码中可能出现的问题。不过,因为涉及 I/O 操做,使用 print 来打印信息会消耗较多的系统资源。同时,这些输出数据极可能会暴露 App 的执行细节,因此咱们在发布正式版时还须要屏蔽掉这些输出。async
不过最工程化的作法是读取项目配置文件,根据运行环境来开启日志调试功能。为了根据不一样的运行环境来开启日志调试功能,咱们可使用 Flutter 提供的debugPrint 来代替 print。debugPrint 函数一样会将消息打印至控制台,但与 print 不一样的是,它提供了定制打印的能力。也就是说,咱们能够向 debugPrint 函数,赋值一个函数声明来自定义打印行为。函数
好比在下面的代码中,咱们将 debugPrint 函数定义为一个空函数体,这样就能够实现一键取消打印的功能了。工具
debugPrint = (String message, {int wrapWidth}) {};//空实现
在 Flutter 中,咱们可使用不一样的 main 文件来表示不一样环境下的入口。一样,在Flutter开发中,能够经过 main.dart 与 main-dev.dart,去分别定义生产环境与开发环境不一样的打印日志行为。布局
在下面的例子中,咱们将生产环境的 debugPrint 定义为空实现,将开发环境的 debugPrint 定义为同步打印数据,以下所示。开发工具
//main.dart void main() { // 将debugPrint指定为空的执行体, 因此它什么也不作 debugPrint = (String message, {int wrapWidth}) {}; runApp(MyApp()); } //main-dev.dart void main() async { // 将debugPrint指定为同步打印数据 debugPrint = (String message, {int wrapWidth}) => debugPrintSynchronously(message, wrapWidth: wrapWidth); runApp(MyApp()); }
能够看到,在代码实现上,咱们只要将应用内全部的 print 都替换成 debugPrint,就能够知足开发环境下打日志的需求,也能够保证生产环境下应用的执行信息不会被意外打印。测试
输出日志当然方便,但若是要想获取更为详细,或是粒度更细的上下文信息,静态调试的方式很是不方便。这时,咱们须要更为灵活的动态调试方法,即断点调试。断点调试可让代码在目标语句上暂停,让程序逐条执行后续的代码语句,来帮助咱们实时关注代码执行上下文中全部变量值的详细变化过程。优化
Android Studio 提供了断点调试的功能,调试 Flutter 应用与调试原生 Android 代码的方法彻底同样,具体能够分为三步,即标记断点、调试应用、查看信息。spa
下面以 Flutter 默认的计数器应用模板为例,观察代码中 _counter 值的变化,体会断点调试的全过程。debug
首先是标记断点。既然咱们要观察 _counter 值的变化,所以在界面上展现最新的 _counter 值时添加断点,去观察其数值变化是最理想的。所以,咱们在行号右侧点击鼠标,能够把断点加载到初始化 Text 控件所示的位置。
在下图的例子中,咱们为了观察 _counter 在等于 20 的时候是否正常,还特地设置了一个条件断点 _counter==20,这样调试器就只会在第 20 次点击计数器按钮时暂停下来。
添加断点后,对应的行号将会出现圆形的断点标记,并高亮显示整行代码。到此,断点就添加好了。固然,咱们还能够同时添加多个断点,以便更好地观察代码的执行过程。
接下来则是调试应用了。和以前经过点击Run 按钮的运行方式不一样,这一次咱们须要点击工具栏上的虫子图标,以调试模式启动 App,以下图所示。
等调试器初始化好后,咱们的程序就启动了。因为设置了断点,因此当代码运行到了断点位置,自动进入了 Debug 视图模式,以下图所示。
按照功能的不一样,能够把 Debug 视图模式划分为 4 个区域,即 A 区控制调试工具、B 区步进调试工具、C 区帧调试窗口、D 区变量查看窗口。
控制调试工具区域主要用来控制调试的执行状况,以下图所示。
咱们能够点击继续执行按钮来让程序继续运行、点击终止执行按钮来让程序终止运行、点击从新执行按钮来让程序从新启动,或是在程序正常执行时,点击暂停执行按钮按钮来让程序暂停运行。固然,咱们能够点击编辑断点按钮来编辑断点信息,或是点击禁用断点按钮来取消断点。
步进调试工具区域主要用来控制断点的步进状况,以下图所示。
能够点击单步跳过按钮来让程序单步执行(但不会进入方法体内部)、点击单步进入或强制单步进入按钮让程序逐条语句执行,甚至还能够点击运行到光标处按钮让程序执行到在光标处。认为断点所在的方法体已经无需执行时,则能够点击单步跳出按钮让程序马上执行完当前进入的方法,从而返回方法调用处的下一行。担任,还能够点击表达式计算按钮来经过赋值或表达式方式修改任意变量的值。
C 区用来指示当前断点所包含的函数执行堆栈,D 区则是其堆栈中的函数帧所对应的变量。
除了输出日志、断点调试,布局分析也是开发中不可缺乏的代码优化手段。借助Flutter提供的Flutter Inspector 可视化工具,能够帮助咱们诊断布局问题。打开Android Studio,而后点击工具栏上的“Open DevTools”按钮便可启动 Flutter Inspector,以下图所示。
随后,Android Studio 会打开浏览器,将Flutter应用程序的的 Widget 树结构展现在面板中。能够看到,Flutter Inspector 所展现的 Widget 树结构,与代码中实现的 Widget 层次是一一对应的。
除了进行布局调试外,还可使用Flutter Inspector进行布局调优。
除了Android Studio外,VSCode也是一款比较常见的Flutter应用程序开发工具。使用VSCode提供的图形化调试界面,开发者能够很方便的进行Flutter应用的调试工做。使用VSCode打开Flutter项目,而后点击VSCode的断点调试按钮便可开启调试,以下图所示。须要说明的是,第一次使用VSCode进行断点调试时,须要先安装并激活Dart DevTools调试工具。若是不肯定是否绑定过DevTools工具,可使用快捷键【command+shift+p】打开VSCode工具栏,而后输入Open DevTools打开调试窗口。而后,在须要调试的代码处设置断点,点击左上方的开启调试按钮开启调试便可。当代码运行到断点处时,就会停留在断点处,而后就能够进行相关调试操做。