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

news2024/11/25 19:51:42

目录

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 行打了一个断点,一旦代码执行到这一行就会暂停,这时我们可以看到当前上下文所有变量的值,然后可以选择一步一步的执行代码。

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 里安装和使用开发者工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/702603.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyEcharts 学习总结

—— 如何用 pyecharts 绘制一切你想象得到的交互式图表&#xff1f; pyecharts 分为 v0.5.x 和 v1.0.0 两个版本&#xff0c;这篇总结针对新版本。 本文不包含基础例子的演示&#xff0c;主要记录一些细节方面的理解。示例看 gallery.pyecharts.org 一、简介 – Echarts &am…

基于Java网上手机商城设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

js获取文字的宽度

通过canvas api 获取文字宽度 const getTextWidth () > {const measureText document.createElement("canvas");const ctx measureText.getContext(2d)!return (name: string) > {const { width } ctx.measureText(name);return width 20 px} }const ge…

Java版企业工程项目管理系统源码-全面的工程项目管理+spring cloud

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈&#xff0c;内卷严重&#xff0c…

FTP-读取指定目录下的文件,上传到FTP服务器,一键复制黏贴,就是这么丝滑~

背景&#xff1a;需要定时将服务器下的日志文件上传到指定FTP服务器的目录下&#xff0c;并通知第三方平台文件已上传。 FTP服务器模拟工具&#xff1a; application.yml配置&#xff1a; spring:logfilepath: /home/jboss/server/default/log# ftp配置ftp:ip: 192.*****port…

ChatGLM-6B部署、实战与微调

文章目录 摘要下载chatglm-6b下载模型文件推理代码调用网页版的Demo网页版的Demo2命令行 Demo 部署API部署低成本部署模型量化CPU 部署Mac 部署多卡部署 训练与微调软件依赖下载数据集训练P-Tuning v2评估P-Tuning v2训练的模型部署P-Tuning v2训练的模型量化全参数Finetune 训…

回归预测 | MATLAB实现PSO-CNN粒子群算法优化卷积神经网络的数据多输入单输出回归预测

回归预测 | MATLAB实现PSO-CNN粒子群算法优化卷积神经网络的数据多输入单输出回归预测 目录 回归预测 | MATLAB实现PSO-CNN粒子群算法优化卷积神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 回归预测 | MATLAB实现PSO-CNN粒子群算法优…

计算机网络 套接字函数 | socket、bind、listen、accept、connect

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

红外雨量计(光学雨量传感器)在船舶航行中的应用

红外雨量计&#xff08;光学雨量传感器&#xff09;在船舶航行中的应用 红外雨量计是一种可靠的测量降雨量的设备&#xff0c;其原理是利用红外线的反射和漏射来测量降雨量。在船舶航行中&#xff0c;降雨对航行和安全都具有重要影响&#xff0c;因此红外雨量计的应用可以提高…

Linux 内核源代码情景分析(二)

系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核 Linux 设备驱动程序 Linux设备驱动开发详解 深入理解Linux虚拟内存管理 Linux 内核源代码情景分析&#xff08;一&#xff09; Linux 内核源代码情景分析&#xff08;二&#xff09; 文章目录 系列文章目录第 4 章 进程…

如何获取科技项目验收测试报告,有什么作用?

科技项目验收测试报告是科技项目验收的重要文件&#xff0c;它对项目的开发过程和测试结果进行了全面的总结和评估。获取科技项目验收测试报告可以帮助项目组了解项目的测试情况和可靠性&#xff0c;从而对项目的质量进行评估和提升。本文将介绍如何获取科技项目验收测试报告&a…

el-table花式操作,含合并求和、双表齐动 等等

1.指定行单元格&#xff0c;合并求和 el-table&#xff0c;提供的行合并&#xff0c;我是没找到单元格可以合并求和的&#xff0c;就用了操作document来 合并单元格&#xff0c;大家可以参考参考 上面这张表&#xff0c;第1 2 两行&#xff0c;数据是一样的&#xff0c;3 4 两…

ES架构原理分析

节点职责 节点按照职责可以分为&#xff1a; master节点数据节点协调节点 节点类型可以进行单独配置。默认情况下&#xff0c;集群不会对节点角色进行划分&#xff0c;所有节点都是平等的&#xff0c;可以担任所有的职责。但是在生产环境中需要对这些节点的角色进行最优划分…

HAL库记录-SDIO外设SD卡

正点原子--阿波罗开发板STM32F429IGT6 1.STM32CubeMX配置 2.生成的代码 /*** Enable DMA controller clock*/ void MX_DMA_Init(void) {/* DMA controller clock enable */__HAL_RCC_DMA2_CLK_ENABLE();/* DMA interrupt init *//* DMA2_Stream3_IRQn interrupt configuratio…

CSS差缺补漏之《高频面试题----如何使元素水平垂直居中?》

面试中经常会被问到如何使元素水平垂直居中&#xff0c;有哪些方法可以做到&#xff1f; 针对此问题&#xff0c;特意总结如下~ 方法一&#xff1a; 定位&#xff08;主要是值子绝父相&#xff09;与margin负值配合----依赖于子元素宽/高 (使用绝对定位或固定定位后&#xff0c…

GitLab无法提交大文件的问题

GitLab无法提交大文件的问题 问题描述 GitLab 当提交大文件时遇到如下报错 MYOPS001MYOPS001 MINGW64 /e/work/GitLab/system-deploy (main) $ git push Enumerating objects: 91, done. Counting objects: 100% (91/91), done. Delta compression using up to 16 threads C…

ARM-异常中断处理概述(五)

文章目录 控制程序执行流程ARM 体系中异常中断种类 控制程序执行流程 在 ARM 体系中通常有以下 3 种方式控制程序的执行流程&#xff1a; 在正常程序中执行过程中&#xff0c;每执行一条 ARM 指令&#xff0c;程序计数寄存器 PC 的值加 4 个字节&#xff1b;每执行一条 Thumb…

Python车道线识别

最近找了一款车道线识别的代码&#xff0c;可以准确识别出车道线&#xff0c;里面的视频路径可以切换为自己的视频&#xff0c;现在我以自带的视频数据展示效果 图片中可以准确识别车的车道线&#xff1a; 下面给出一部分源代码&#xff1a; import cv2 import numpy as np i…

汽车统一bootloaderv2.0版本 翻译

统一bootloader系统 统一bootloader范围 下图展示了PC通过适配器与ECU连接。高亮公布部分是ECU和PC共同的。所有平台都是一样的。 统一bootloader关键特征 UDS(ISO14229)TP(ISO1765-2/CAN,ISO17987-2/LIN)Flash驱动包括共同的要求从主机下载Flash驱动bootloader检测APP完整…

元宇宙赋能数字文创 | 蓝海创意云受邀发表瑶海区文化创意产业数字化高峰论坛主题演讲

2023年6月29日&#xff0c;在合肥市文化旅游局的指导下&#xff0c;由中共合肥市瑶海区委员会和合肥市瑶海区人民政府主办的“2023瑶海文化创意产业数字化高峰论坛”于合肥市长江180艺术街区召开&#xff0c;本次论坛以“传承创新&#xff0c;数字引领”为主题&#xff0c;探索…