Flutter学习四:Flutter开发基础(六)调试Flutter应用

这篇具有很好参考价值的文章主要介绍了Flutter学习四:Flutter开发基础(六)调试Flutter应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

0 引言

1 调试Flutter应用

1.1 日志与断点

1.1.1 debugger() 声明

1.1.2 print和debugPrint

1.1.3 调试模式、中间模式、发布模式

1.1.4 断点

1.2 调试应用程序层

1.2.1 转储Widgets树

1.2.2  转储渲染树

1.2.3 转储Layer树

1.2.4 转储语义树

1.2.5 调度(打印帧的开始和结束)

1.2.6 可视化调试

1.2.7 调试动画

1.2.8 调试性能问题

1.2.9 统计应用启动时间

1.2.10  跟踪Dart代码性能

1.3 官方可视化调试工具DevTools


0 引言

本文是对第二版序 | 《Flutter实战·第二版》 (flutterchina.club)的学习和总结。

1 调试Flutter应用

1.1 日志与断点

1.1.1 debugger() 声明

当使用Dart Observatory(调试模式时自动启用),可以使用debugger()语句插入编程式断点。

import 'dart:developer';

/*
  debugger()语句采用一个可选的when参数,可以指定该参数仅在特定条件为真时中断
*/
void someFunction(double offset) {
  debugger(when: offset > 30.0);
  // ...
}

1.1.2 print和debugPrint

  • Dart  print()功能将输出到系统控制台,可以使用flutter logs来查看它。如果一次输出太多,Android有时会丢弃一些日志行。
  • 推荐使用Flutter的foundation库中的debugPrint(),它封装了 print,将一次输出的内容长度限制在一个级别(内容过多时会分批输出),避免被Android内核丢弃。

1.1.3 调试模式、中间模式、发布模式

  • 在Flutter应用调试过程中,Dart assert语句被启用,当某个规则被违反时,就会在控制台打印错误日志,并带上一些上下文信息来帮助追踪问题的根源。
  • 发布模式会关闭Observatory调试器,使用flutter run --release运行应用程序即可打开发布模式。
  • 中间模式“profile mode”可以关闭除Observatory之外所有的调试辅助工具,使用flutter run --profile运行应用程序即可打开中间模式。

1.1.4 断点

开发过程中,断点是最实用的调试工具之一,以 Android Studio 为例:比如在 93 行打了一个断点,一旦代码执行到这一行就会暂停,这时我们可以看到当前上下文所有变量的值,然后可以选择一步一步的执行代码。

Flutter学习四:Flutter开发基础(六)调试Flutter应用,Flutter,flutter,学习

1.2 调试应用程序层

Flutter框架的每一层都提供了将其当前状态或事件转储(dump)到控制台(使用debugPrint)的功能。

1.2.1 转储Widgets树

  • 要转储Widgets树的状态,请调用debugDumpApp()
  • 需要在调用runApp()之后调用
  • 不能在build()方法内调用
  • 不要在布局或绘制阶段调用
  • 从frame 回调或事件处理器中调用是最佳方案
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: AppHome(),
    ),
  );
}

class AppHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: TextButton(
          onPressed: () {
            // 当按钮从被按下变为被释放时debugDumpApp()被调用
            debugDumpApp();
          },
          child: Text('Dump App'),
        ),
      ),
    );
  }
}

调用后输出这样的内容(精确的细节会根据框架的版本、设备的大小等等而变化): 

I/flutter ( 6559): WidgetsFlutterBinding - CHECKED MODE
I/flutter ( 6559): RenderObjectToWidgetAdapter<RenderBox>([GlobalObjectKey RenderView(497039273)]; renderObject: RenderView)
I/flutter ( 6559): └MaterialApp(state: _MaterialAppState(1009803148))
I/flutter ( 6559):  └ScrollConfiguration()
I/flutter ( 6559):   └AnimatedTheme(duration: 200ms; state: _AnimatedThemeState(543295893; ticker inactive; ThemeDataTween(ThemeData(Brightness.light Color(0xff2196f3) etc...) → null)))
I/flutter ( 6559):    └Theme(ThemeData(Brightness.light Color(0xff2196f3) etc...))
I/flutter ( 6559):     └WidgetsApp([GlobalObjectKey _MaterialAppState(1009803148)]; state: _WidgetsAppState(552902158))
I/flutter ( 6559):      └CheckedModeBanner()
I/flutter ( 6559):       └Banner()
I/flutter ( 6559):        └CustomPaint(renderObject: RenderCustomPaint)
I/flutter ( 6559):         └DefaultTextStyle(inherit: true; color: Color(0xd0ff0000); family: "monospace"; size: 48.0; weight: 900; decoration: double Color(0xffffff00) TextDecoration.underline)
I/flutter ( 6559):          └MediaQuery(MediaQueryData(size: Size(411.4, 683.4), devicePixelRatio: 2.625, textScaleFactor: 1.0, padding: EdgeInsets(0.0, 24.0, 0.0, 0.0)))
I/flutter ( 6559):           └LocaleQuery(null)
I/flutter ( 6559):            └Title(color: Color(0xff2196f3))
... #省略剩余内容

1.2.2  转储渲染树

  • 调试布局问题时,转储Widget树可能不够详细,需要转储渲染树
  • 要转储渲染树,请调用debugDumpRenderTree()
  • 要调用debugDumpRenderTree(),需要添加import'package:flutter/rendering.dart'

 对于上面的例子,它会输出:

I/flutter ( 6559): RenderView
I/flutter ( 6559):  │ debug mode enabled - android
I/flutter ( 6559):  │ window size: Size(1080.0, 1794.0) (in physical pixels)
I/flutter ( 6559):  │ device pixel ratio: 2.625 (physical pixels per logical pixel)
I/flutter ( 6559):  │ configuration: Size(411.4, 683.4) at 2.625x (in logical pixels)
I/flutter ( 6559):  │
I/flutter ( 6559):  └─child: RenderCustomPaint
I/flutter ( 6559):    │ creator: CustomPaint ← Banner ← CheckedModeBanner ←
I/flutter ( 6559):    │   WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)] ←
I/flutter ( 6559):    │   Theme ← AnimatedTheme ← ScrollConfiguration ← MaterialApp ←
I/flutter ( 6559):    │   [root]
I/flutter ( 6559):    │ parentData: <none>
I/flutter ( 6559):    │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):    │ size: Size(411.4, 683.4)
... # 省略

1.2.3 转储Layer树

  • 调试合成问题,调用debugDumpLayerTree()
  • 可以理解为渲染树是可以分层的,而最终绘制需要将不同的层合成起来,而Layer则是绘制时需要合成的层

对于上面的例子,它会输出下图内容。这是根LayertoStringDeep输出的。根部的变换是应用设备像素比的变换; 在这种情况下,每个逻辑像素代表3.5个设备像素。

I/flutter : TransformLayer
I/flutter :  │ creator: [root]
I/flutter :  │ offset: Offset(0.0, 0.0)
I/flutter :  │ transform:
I/flutter :  │   [0] 3.5,0.0,0.0,0.0
I/flutter :  │   [1] 0.0,3.5,0.0,0.0
I/flutter :  │   [2] 0.0,0.0,1.0,0.0
I/flutter :  │   [3] 0.0,0.0,0.0,1.0
I/flutter :  │
I/flutter :  ├─child 1: OffsetLayer
I/flutter :  │ │ creator: RepaintBoundary ← _FocusScope ← Semantics ← Focus-[GlobalObjectKey MaterialPageRoute(560156430)] ← _ModalScope-[GlobalKey 328026813] ← _OverlayEntry-[GlobalKey 388965355] ← Stack ← Overlay-[GlobalKey 625702218] ← Navigator-[GlobalObjectKey _MaterialAppState(859106034)] ← Title ← ⋯
I/flutter :  │ │ offset: Offset(0.0, 0.0)
I/flutter :  │ │
I/flutter :  │ └─child 1: PictureLayer
I/flutter :  │
I/flutter :  └─child 2: PictureLayer

1.2.4 转储语义树

  • 语义树:呈现给系统可访问性API的树
  • 转储语义树,要调用debugDumpSemanticsTree() 
  •  要调用debugDumpSemanticsTree() ,必须首先启用辅助功能,例如启用系统辅助工具或SemanticsDebugger

对于上面的例子,它会输出:

I/flutter : SemanticsNode(0; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter :  ├SemanticsNode(1; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter :  │ └SemanticsNode(2; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4); canBeTapped)
I/flutter :  └SemanticsNode(3; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter :    └SemanticsNode(4; Rect.fromLTRB(0.0, 0.0, 82.0, 36.0); canBeTapped; "Dump App")

1.2.5 调度(打印帧的开始和结束)

  • 切换debugPrintBeginFrameBanner和debugPrintEndFrameBanner布尔值可以将帧的开始和结束打印到控制台,找出相对于帧的开始/结束事件发生的位置。
  • debugPrintScheduleFrameStacks可以用来打印导致当前帧被调度的调用堆栈

例如:

I/flutter : ▄▄▄▄▄▄▄▄ Frame 12         30s 437.086ms ▄▄▄▄▄▄▄▄
I/flutter : Debug print: Am I performing this work more than once per frame?
I/flutter : Debug print: Am I performing this work more than once per frame?
I/flutter : ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

1.2.6 可视化调试

所有这些标志只能在调试模式下工作。

通常,Flutter框架中以“debug...” 开头的任何内容都只能在调试模式下工作。

设置debugPaintSizeEnabledtrue以可视方式调试布局问题:

  • 这是来自rendering库的布尔值。
  • 它可以在任何时候启用,并在为true时影响绘制。
  • 设置它的最简单方法是在void main()的顶部设置。

当它被启用时,所有的盒子都会得到一个明亮的深青色边框:

  • padding(来自widget如Padding)显示为浅蓝色,
  • 子widget周围有一个深蓝色框,
  • 对齐方式(来自widget如Center和Align)显示为黄色箭头,
  • 空白(如没有任何子节点的Container)以灰色显示。

debugPaintBaselinesEnabled做了类似的事情,但对于具有基线的对象,文字基线以绿色显示,表意(ideographic)基线以橙色显示。

debugPaintPointersEnabled标志打开一个特殊模式,任何正在点击的对象都会以深青色突出显示。 这可以帮助我们确定某个对象是否以某种不正确的方式进行hit测试(Flutter检测点击的位置是否有能响应用户操作的widget),例如,如果它实际上超出了其父项的范围,首先不会考虑通过hit测试。

debugPaintLayerBordersEnabled标志调试合成图层,例如以确定是否以及在何处添加RepaintBoundary widget。该标志用橙色或轮廓线标出每个层的边界,或者使用debugRepaintRainbowEnabled标志重绘时,该层会被一组旋转色所覆盖。

1.2.7 调试动画

调试动画最简单的方法是减慢它们的速度:

  • 将timeDilation (opens new window)变量(在scheduler库中)设置为大于1.0的数字,例如50.0。
  • 最好在应用程序启动时只设置一次。
  • 如果在运行中更改它,尤其是在动画运行时将其值改小,则在观察时可能会出现倒退。

1.2.8 调试性能问题

  • 要了解应用程序导致重新布局或重新绘制的原因,分别设置debugPrintMarkNeedsLayoutStacks和 debugPrintMarkNeedsPaintStacks标志。
  •  每当渲染盒被要求重新布局和重新绘制时,这些都会将堆栈跟踪记录到控制台。
  • 可以使用services库中的debugPrintStack()方法按需打印堆栈痕迹。

1.2.9 统计应用启动时间

  • 要收集有关Flutter应用程序启动所需时间的详细信息,
  • 可以在运行flutter run时使用trace-startupprofile选项。
$ flutter run --trace-startup --profile

跟踪输出保存为start_up_info.json,在Flutter工程目录在build目录下。输出列出了从应用程序启动到这些跟踪事件(以微秒捕获)所用的时间:

  • 进入Flutter引擎时.
  • 展示应用第一帧时.
  • 初始化Flutter框架时.
  • 完成Flutter框架初始化时.

例如 :

{
  "engineEnterTimestampMicros": 96025565262,
  "timeToFirstFrameMicros": 2171978,
  "timeToFrameworkInitMicros": 514585,
  "timeAfterFrameworkInitMicros": 1657393
}

1.2.10  跟踪Dart代码性能

跟踪和测量Dart任意代码段的wall/CPU时间(类似Android上使用systrace):

  • 运行flutter run时带有--profile标志,
  • 使用dart:developer的Timeline工具来包含你想测试的代码块,
  • 打开你应用程序的Observatory timeline页面,在“Recorded Streams”中选择‘Dart’复选框,并执行你想测量的功能。
  • 刷新页面将在Chrome的跟踪工具中显示应用按时间顺序排列的timeline记录。
Timeline.startSync('interesting function');
// iWonderHowLongThisTakes();
Timeline.finishSync();

1.3 官方可视化调试工具DevTools

Flutter DevTools 是一套 Dart 和 Flutter 的性能调试工具。

它将各种调试工具和能力集成在一起,并提供可视化调试界面。

可以用 Flutter DevTools 开发工具来实现的操作:

  • 检查 Flutter 应用程序的 UI 组件布局和状态;

  • 在 Flutter 应用程序中诊断 UI 性能过低的问题;

  • Flutter 和 Dart 应用的 CPU 性能检测;

  • 为 Flutter 应用进行网络性能检测;

  • 为 Flutter 或 Dart 应用进行源码级的调试;

  • 在 Flutter 或 Dart 命令行应用中测试内存问题;

  • 查看有关正在运行的Flutter或Dart命令行应用程序的常规日志和诊断信息。
  • 查看正在运行的 Flutter 或 Dart 的命令行应用程序相关的常规日志和诊断信息。

 在 Android Studio 上安装和运行开发者工具

 在 VS Code 里安装和使用开发者工具文章来源地址https://www.toymoban.com/news/detail-517016.html

到了这里,关于Flutter学习四:Flutter开发基础(六)调试Flutter应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零基础到精通Flutter开发:一步步打造跨平台应用

    💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】 🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】 💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 导言 Flutter是一种流行的开发框架,可以用来构建美观、高性能且跨平台的移动应

    2024年02月08日
    浏览(68)
  • 【粉丝福利社】Flutter小白开发——跨平台客户端应用开发学习路线(文末送书-完结)

    🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,51CTO博客专家等。 🏆《近期荣誉》:

    2024年01月16日
    浏览(71)
  • VSCode 开发flutter 实现安卓设备远程调试

    目前只找到了安卓的调试方案😬。 1首先安装 ADB Commanads for VSCode扩展 并且必须确保ADB已经添加到系统环境变量中 如未添加请按照下面的方式添加,如添加请直接跳到下面。 2添加环境变量(windows可参考,mac忽略此项) 我将ADB安装到这个目录下,请查找自己的安装目录。 将

    2024年02月02日
    浏览(38)
  • 【粉丝福利社】Flutter小白开发——跨平台客户端应用开发学习路线(文末送书-进行中)

    🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,51CTO博客专家等。 🏆《近期荣誉》:

    2024年01月18日
    浏览(79)
  • VIVO手机调试Flutter应用卡在启动页面 黑屏 白屏问题

    vivo系统android13发现调试flutter应用卡在启动页 并且没有任何报错,问题如下 https://github.com/flutter/flutter/issues/117019 我猜这跟vivo瞎几把隐藏系统log有关。 需要你提供imei1给vivo开发授权才能正常调试。 步骤如下 1 拨号盘输入 *#06# 长按复制imei1备用 2.添加企业人员联系 3002261823 3

    2024年02月13日
    浏览(43)
  • flutter开发实战-Release环境与Debug调试环境配置实现

    flutter开发实战-Release环境与Debug调试环境配置实现 在开发中,我们经常遇到Release与Debug相关请求等配置隔离。这里记录之前的实现方案。 在实现之前,我们需要先看下git_it 在开发过程中,需要App的部分逻辑与Widget分离。git_it和provider都可以用作状态管理,这里使用的是git_i

    2024年02月16日
    浏览(44)
  • Flutter 开发者工具 Android Studio 开发Flutter应用

    Flutter 开发者工具 在 Android Studio 开发Flutter应用 🔥 Android Studio 版本更新 🔥 Android Studio Check for Update Connection failed ​ 解决方案 ​    ​  🔥 编辑代码,和查看问题 🔥  Dart 插件 可以做到如下几点 :  语法高亮显示。 基于多种类型分析的代码补全。 定位到类型的声明(

    2024年02月15日
    浏览(110)
  • Flutter移动应用开发 - 01 Flutter初次安装、模拟器配置教程(手把手版)

    首先先安装一个编辑器,这边选用的是Android Studio(Android Studio)。Android Studio的下载和项目创建平平无奇,唯一可能有问题的就是gradle文件的下载,如果没翻墙的话需要手动下载和配置,在此不多介绍。 接下来文件的配置。 官网下载并解压Flutter SDK 版本列表 - Flutter 中文文档

    2023年04月25日
    浏览(50)
  • 【Flutter】创建应用顶级组件,应用根组件 (学习记录)

    在 Flutter 中,应用的顶级组件或根组件通常是在 main() 函数中通过 runApp() 方法创建的。这个组件通常是一个 MaterialApp、CupertinoApp、GetMaterialApp 或其他类似的应用框架组件。 以下是一个创建 MaterialApp 作为根组件的示例: 在这个示例中,MyApp 是应用的根组件,它返回了一个 Ma

    2024年02月04日
    浏览(35)
  • Flutter开发笔记 —— sqflite插件数据库应用

    今天在观阅掘金大佬文章的时候,了解到了该 sqflite 插件,结合官网教程和自己实践,由此总结出该文,希望对大家的学习有帮助! Flutter的 SQLite 插件。支持 iOS、Android 和 MacOS。 支持事务和batch模式 打开时自动进行版本管理 插入/查询/更新/删除查询的助手 iOS 和 Android 上的

    2024年02月04日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包