如何调试flutter应用

The Dart Analyzer

这个工具帮助你分析代码,发现可能的错误。编程

运行命令行

终端进入flutter工程所在目录,执行flutter analyzejson

使用IntelliJ IDEA

Dart Observatory

dart语句级单步调试器和分析器api

运行命令行

终端进入flutter工程所在目录,执行flutter run命令运行app,运行的时候,在控制台能够看到一个Observatory URL(如http://127.0.0.1:8100/),咱们能够经过浏览器打开,直接用语句级的单步调试程序链接到你的应用程序。浏览器

使用IntelliJ IDEA

IDE内置调试器,运行的时候选择debug按钮intellij-idea

debugger()

使用debugger()语句插入编程式断点,调用这个方法须要import 'dart:developer'。该debugger()语句带有一个可选when参数,您能够指定该参数仅在特定条件为真时中断,以下所示:app

void someFunction(double offset) {
  debugger(when: offset > 30.0);
  // ...
}

使用print()方法打印日志到控制台

咱们可使用flutter logs来查阅日志,这个命令基本上是对adb logcat 命令作了一层封装。框架

若是打印日志过多,Android的作法是设置日志优先级或者有时会丢弃一些日志行。为了不这种状况,咱们可使用debugPrint()方法,这个方法是对print()方法作了一层包装,将输出限制在一个级别,避免被Android内核丢弃。less

flutter框架中的许多类都有有用的toString实现。按照惯例,这些输出一般包括runtimeType对象的一行,一般在ClassName表格中。树中使用的某些类也具备从那一点返回整个子树的多行描述的toStringDeep方法。有些详细实现了toString方法的类,有一个相应的只返回类型或者对对象只有一两个词语简短描述的toStringShort方法。ide

调试模式断言

在开发过程当中,强烈建议您使用Flutter的“调试”模式,有时也称为“检查”模式。若是你使用flutter run命令,调试模式是默认的。在这种模式下,Dart assert语句被启用,Flutter框架使用它来执行许多运行时检查,验证赋值是否合法。函数

当一个赋值不合法时,它会向控制台报告,并提供一些上下文信息来帮助追踪问题的根

import 'package:flutter/material.dart';

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

class AppHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Material(
      child: new Center(
        child: new FlatButton(
          onPressed: () {
            debugDumpApp();
          },
          child: new Text('Dump App'),
        ),
      ),
    );
  }
}

 

源。

要关闭调试模式并使用发布模式,请使用flutter run --release运行您的应用程序,这也关闭了Observatory调试器。咱们也可用--profile替代--release, 一种关闭除了Observatory调试器以外的全部辅助工具的中间模式,也称为“分析模式”。

转储应用程序状态

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

控件层

咱们可使用debugDumpApp()转储Widgets库的状态,示例:

import 'package:flutter/material.dart';

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

class AppHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Material(
      child: new Center(
        child: new FlatButton(
          onPressed: () {
            debugDumpApp();
          },
          child: new Text('Dump App'),
        ),
      ),
    );
  }
}

控制台会输出一个“扁平化”的树,显示了经过各类build函数建立的全部控件。

渲染层

若是您尝试调试布局问题,那么控件层的树可能不够详细。在这种状况下,您能够经过调用debugDumpRenderTree()转储渲染树 。和debugDumpApp()用法同样,除了布局或绘画阶段以外,您能够随时调用它。约定俗成,咱们最好在帧回调 或事件处理时调用它。

要调用debugDumpRenderTree(),咱们须要import 'package:flutter/rendering.dart';

上面示例调用debugDumpRenderTree(),输出结果以下所示:

 

渲染层

若是您尝试调试布局问题,那么控件层的树可能不够详细。在这种状况下,您能够经过调用debugDumpRenderTree()转储渲染树 。和debugDumpApp()用法同样,除了布局或绘画阶段以外,您能够随时调用它。约定俗成,咱们最好在帧回调 或事件处理时调用它。

要调用debugDumpRenderTree(),咱们须要import 'package:flutter/rendering.dart';

上面示例调用debugDumpRenderTree(),输出结果以下所示:

 

图层

若是您正在尝试调试混合问题,则可使用 debugDumpLayerTree()。对于上面的例子,它会输出:

这是在根图层对象上调用toStringDeep的输出。

根的变换是应用设备像素比的变换;在本例中,每一个逻辑像素的比率为3.5个设备像素。

RepaintBoundary控件在渲染层中建立了一个新的图层RenderRepaintBoundary,一般用来减小须要从新绘制的层数。

语义

您还可使用debugDumpSemanticsTree()得到语义树(该树存在于系统可访问的api中)的转储。要使用这个功能,您必须首先设置容许访问,例如,经过启用系统可访问性工具或SemanticsDebugger

上面的例子调用debugDumpSemanticsTree(),控制台将会输出下面结果:

https://img-blog.csdn.net/20171227193605109?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvam9obldjaGV1bmc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

可视化调试

你还能够经过设置debugPaintSizeEnabled为true来更直观的调试布局问题,这是渲染库中的一个布尔变量,当该变量为true时,它能够随时生效,而且影响全部地方的绘制。最简单的办法是在void main()主函数顶部入口去设置它。

当咱们打开可视化调试时,全部子控件内边距会有一个明亮渐变的深蓝色边框,控件中间显示一个黄色箭头,控件间距会显示灰色。

debugPaintBaselinesEnabled的功能相似于对象的基准线,字母基线显示亮绿色,表意基线显示橙色。

debugPaintPointersEnabled标志位会打开一种特殊模式,让全部的对象都突出显示,这个能够帮助你发现哪个对象不能正确的进行测试,好比,某个对象在其父类的范围以外,就不会第一时间被考虑进行命中测试。

若是您尝试调试混合图层,例如,肯定是否以及在何处添加RepaintBoundary控件,可使用debugPaintLayerBordersEnabled标志位,它使用橙色来绘制每一个图层的边界,或者用debugRepaintRainbowEnabled标志位,当图层从新绘制时,它将让图层显示旋转的色彩。

全部这些标志位只在调试模式下工做。通常来讲,在Flutter框架中,任何以“debug…”开头的变量或方法,都只能在调试模式下有效。

调试动画

调试动画最简单的方法是减慢它们的速度。为此,将timeDilation变量(在scheduler库中)设置为大于1.0的数字,例如50.0。最好在应用程序启动时只设置一次。若是您在运行中更改它,尤为是在动画运行时将其值变小,则框架可能会观察到时间倒退,这可能会致使断言,而且一般会影响效果。

调试性能问题

要知道致使你应用程序从新布局或从新绘制的缘由,您能够分别设置 debugPrintMarkNeedsLayoutStacks 和 debugPrintMarkNeedsPaintStacks标志。

每当渲染框被要求从新布局和从新绘制时,都会随时将堆栈跟踪日志打印到控制台。若是这种方法对你有用,你可使用services库中的debugPrintStack()方法按需打印本身的堆栈跟踪日志。

测试应用程序启动时间

要收集有关Flutter应用程序启动所需时间的详细信息,能够执行以下命令:

$ flutter run --trace-startup --profile

跟踪日志被保存在你的Flutter工程build目录下一个叫start_up_info.json的json文件里。日志会列出从应用启动到这些以微秒捕获的跟踪事件所用的时间:

  • 进入Flutter引擎代码的时间

  • 绘制应用第一帧的时间

  • 初始化Flutter框架的时间

  • 完成Flutter框架初始化的时间

例如:

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

跟踪任何Dart代码的性能

要执行自定义性能跟踪,去测量dart任一代码块的

CPU时间和墙上时钟时间,实现相似Android性能分析工具systrace的功能,咱们可使用dart:developer里面的时间轴工具来包装你想测试的代码:

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

而后打开应用分析器的时间轴页面,检查dart记录选项并执行你想测试的功能。 
刷新该页面,将会在Chrome浏览器的跟踪工具中按时间顺序显示应用程序的时间轴记录。

务必使用flutter run --profile命令运行应用程序,以保证运行时性能特征与最终产品的性能紧密匹配。

性能覆盖图

要得到应用程序性能的图形视图, 咱们须要将MaterialApp构造函数的showPerformanceOverlay参数设为true, WidgetsApp构造函数也有相似的参数。 若是你没有使用MaterialApp或者WidgetsApp, 你能够将你的应用程序封装在一个堆栈中,调用new PerformanceOverlay.allEnabled()方法建立一个控件放在堆栈上。

这将显示两个图表:上面是GPU线程花费的时间,下面是CPU线程花费的时间。图中的白线沿垂直轴显示16ms的增量;若是图表通过其中的一条白线,那么你运行速度在60Hz如下,横轴表明框架。图表只会在应用程序绘制时更新,因此若是处于空闲状态,图表将中止移动。

这个操做必定是在发布模式下完成,由于在调试模式下,会故意牺牲性能来换取旨在辅助开发的昂贵的断言,这样结果将是误导性的。

Material网格

当咱们开发实现Material design的应用时,应用上会覆盖一个帮助验证对齐的Material Design基线网格。 为此,在调试模式下,将MaterialApp构造函数的debugShowGrid参数设为true,将会覆盖这样一个网格。

你也能够直接使用GridPaper控件在非Material应用程序上覆盖这样的网格。

相关文章
相关标签/搜索