0
点赞
收藏
分享

微信扫一扫

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

滚过红尘说红尘 2023-07-05 阅读 46

目录

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

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

1.1.4 断点

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

1.2 调试应用程序层

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

1.2.1 转储Widgets树

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  转储渲染树

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

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树

对于上面的例子,它会输出下图内容。这是根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 转储语义树

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

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 调度(打印帧的开始和结束)

例如:

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...” 开头的任何内容都只能在调试模式下工作。

1.2.7 调试动画

1.2.8 调试性能问题

1.2.9 统计应用启动时间

$ flutter run --trace-startup --profile

例如 :

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

1.2.10  跟踪Dart代码性能

Timeline.startSync('interesting function');
// iWonderHowLongThisTakes();
Timeline.finishSync();

1.3 官方可视化调试工具DevTools

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

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

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

 在 VS Code 里安装和使用开发者工具

举报

相关推荐

0 条评论