添加输出代码的方式调试 Flutter 应用

This doc describes debugging features that you can enable in code.For a full list of debugging and profiling tools, see theDebugging page.

Logging

备忘 You can view logs in DevTools’ Logging view or in your system console. This sections shows how to set up your logging statements.

You have two options for logging for your application.The first is to use stdout and stderr.Generally, this is done using print() statements,or by importing dart:io and invoking methods onstderr and stdout. For example:

  1. stderr.writeln('print me');

If you output too much at once, then Android sometimesdiscards some log lines. To avoid this, use debugPrint(),from Flutter’s foundation library. This is a wrapper around printthat throttles the output to a level that avoids being dropped byAndroid’s kernel.

The other option for application logging is to use thedart:developer log() function. This allows you to include abit more granularity and information in the logging output.Here’s an example:

  1. import 'dart:developer' as developer;
  2. void main() {
  3. developer.log('log me', name: 'my.app.category');
  4. developer.log('log me 1', name: 'my.other.category');
  5. developer.log('log me 2', name: 'my.other.category');
  6. }

You can also pass application data to the log call.The convention for this is to use the error: namedparameter on the log() call, JSON encode the objectyou want to send, and pass the encoded string to theerror parameter.

  1. import 'dart:convert';
  2. import 'dart:developer' as developer;
  3. void main() {
  4. var myCustomObject = ...;
  5. developer.log(
  6. 'log me',
  7. name: 'my.app.category',
  8. error: jsonEncode(myCustomObject),
  9. );
  10. }

If viewing the logging output in DevTool’s logging view,the JSON encoded error param is interpreted as a data objectand rendered in the details view for that log entry.

Setting breakpoints

备忘 You can set breakpoints in DevTools’ Debugger, or in the built-in debugger of your IDE. If you want to set breakpoints programmatically, use the following instructions.

You can insert programmatic breakpoints using thedebugger() statement. To use this, you have toimport the dart:developer package at the top ofthe relevant file.

The debugger() statement takes an optional whenargument that you can specify to only break when acertain condition is true, as in the following example:

  1. import 'dart:developer';
  2. void someFunction(double offset) {
  3. debugger(when: offset > 30.0);
  4. // ...
  5. }

Debug flags: application layers

Each layer of the Flutter framework provides a function to dump itscurrent state or events to the console (using debugPrint).

Widget tree

To dump the state of the Widgets library, call debugDumpApp().You can call this more or less any time that the application is not inthe middle of running a build phase (in other words, not anywhere inside abuild() method), so long as the application has built at least once(in other words, any time after calling runApp()).

For example, the following application:

  1. import 'package:flutter/material.dart';
  2. void main() {
  3. runApp(
  4. MaterialApp(
  5. home: AppHome(),
  6. ),
  7. );
  8. }
  9. class AppHome extends StatelessWidget {
  10. @override
  11. Widget build(BuildContext context) {
  12. return Material(
  13. child: Center(
  14. child: FlatButton(
  15. onPressed: () {
  16. debugDumpApp();
  17. },
  18. child: Text('Dump App'),
  19. ),
  20. ),
  21. );
  22. }
  23. }

The prevous app outputs something like the following(the precise details vary by the version of the framework,the size of the device, and so forth):

  1. I/flutter ( 6559): WidgetsFlutterBinding - CHECKED MODE
  2. I/flutter ( 6559): RenderObjectToWidgetAdapter<RenderBox>([GlobalObjectKey RenderView(497039273)]; renderObject: RenderView)
  3. I/flutter ( 6559): MaterialApp(state: _MaterialAppState(1009803148))
  4. I/flutter ( 6559): ScrollConfiguration()
  5. I/flutter ( 6559): AnimatedTheme(duration: 200ms; state: _AnimatedThemeState(543295893; ticker inactive; ThemeDataTween(ThemeData(Brightness.light Color(0xff2196f3) etc...) null)))
  6. I/flutter ( 6559): Theme(ThemeData(Brightness.light Color(0xff2196f3) etc...))
  7. I/flutter ( 6559): WidgetsApp([GlobalObjectKey _MaterialAppState(1009803148)]; state: _WidgetsAppState(552902158))
  8. I/flutter ( 6559): CheckedModeBanner()
  9. I/flutter ( 6559): Banner()
  10. I/flutter ( 6559): CustomPaint(renderObject: RenderCustomPaint)
  11. I/flutter ( 6559): DefaultTextStyle(inherit: true; color: Color(0xd0ff0000); family: "monospace"; size: 48.0; weight: 900; decoration: double Color(0xffffff00) TextDecoration.underline)
  12. 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)))
  13. I/flutter ( 6559): LocaleQuery(null)
  14. I/flutter ( 6559): Title(color: Color(0xff2196f3))
  15. I/flutter ( 6559): Navigator([GlobalObjectKey<NavigatorState> _WidgetsAppState(552902158)]; state: NavigatorState(240327618; tracking 1 ticker))
  16. I/flutter ( 6559): Listener(listeners: down, up, cancel; behavior: defer-to-child; renderObject: RenderPointerListener)
  17. I/flutter ( 6559): AbsorbPointer(renderObject: RenderAbsorbPointer)
  18. I/flutter ( 6559): Focus([GlobalKey 489139594]; state: _FocusState(739584448))
  19. I/flutter ( 6559): Semantics(container: true; renderObject: RenderSemanticsAnnotations)
  20. I/flutter ( 6559): _FocusScope(this scope has focus; focused subscope: [GlobalObjectKey MaterialPageRoute<void>(875520219)])
  21. I/flutter ( 6559): Overlay([GlobalKey 199833992]; state: OverlayState(619367313; entries: [OverlayEntry@248818791(opaque: false; maintainState: false), OverlayEntry@837336156(opaque: false; maintainState: true)]))
  22. I/flutter ( 6559): _Theatre(renderObject: _RenderTheatre)
  23. I/flutter ( 6559): Stack(renderObject: RenderStack)
  24. I/flutter ( 6559): _OverlayEntry([GlobalKey 612888877]; state: _OverlayEntryState(739137453))
  25. I/flutter ( 6559): │└IgnorePointer(ignoring: false; renderObject: RenderIgnorePointer)
  26. I/flutter ( 6559): ModalBarrier()
  27. I/flutter ( 6559): Semantics(container: true; renderObject: RenderSemanticsAnnotations)
  28. I/flutter ( 6559): GestureDetector()
  29. I/flutter ( 6559): RawGestureDetector(state: RawGestureDetectorState(39068508; gestures: tap; behavior: opaque))
  30. I/flutter ( 6559): _GestureSemantics(renderObject: RenderSemanticsGestureHandler)
  31. I/flutter ( 6559): Listener(listeners: down; behavior: opaque; renderObject: RenderPointerListener)
  32. I/flutter ( 6559): ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox)
  33. I/flutter ( 6559): _OverlayEntry([GlobalKey 727622716]; state: _OverlayEntryState(279971240))
  34. I/flutter ( 6559): _ModalScope([GlobalKey 816151164]; state: _ModalScopeState(875510645))
  35. I/flutter ( 6559): Focus([GlobalObjectKey MaterialPageRoute<void>(875520219)]; state: _FocusState(331487674))
  36. I/flutter ( 6559): Semantics(container: true; renderObject: RenderSemanticsAnnotations)
  37. I/flutter ( 6559): _FocusScope(this scope has focus)
  38. I/flutter ( 6559): Offstage(offstage: false; renderObject: RenderOffstage)
  39. I/flutter ( 6559): IgnorePointer(ignoring: false; renderObject: RenderIgnorePointer)
  40. I/flutter ( 6559): _MountainViewPageTransition(animation: AnimationController(⏭ 1.000; paused; for MaterialPageRoute<void>(/))➩ProxyAnimationCubic(0.40, 0.00, 0.20, 1.00)➩Tween<Offset>(Offset(0.0, 1.0) Offset(0.0, 0.0))➩Offset(0.0, 0.0); state: _AnimatedState(552160732))
  41. I/flutter ( 6559): SlideTransition(animation: AnimationController(⏭ 1.000; paused; for MaterialPageRoute<void>(/))➩ProxyAnimationCubic(0.40, 0.00, 0.20, 1.00)➩Tween<Offset>(Offset(0.0, 1.0) Offset(0.0, 0.0))➩Offset(0.0, 0.0); state: _AnimatedState(714726495))
  42. I/flutter ( 6559): FractionalTranslation(renderObject: RenderFractionalTranslation)
  43. I/flutter ( 6559): RepaintBoundary(renderObject: RenderRepaintBoundary)
  44. I/flutter ( 6559): PageStorage([GlobalKey 619728754])
  45. I/flutter ( 6559): _ModalScopeStatus(active)
  46. I/flutter ( 6559): AppHome()
  47. I/flutter ( 6559): Material(MaterialType.canvas; elevation: 0; state: _MaterialState(780114997))
  48. I/flutter ( 6559): AnimatedContainer(duration: 200ms; has background; state: _AnimatedContainerState(616063822; ticker inactive; has background))
  49. I/flutter ( 6559): Container(bg: BoxDecoration())
  50. I/flutter ( 6559): DecoratedBox(renderObject: RenderDecoratedBox)
  51. I/flutter ( 6559): Container(bg: BoxDecoration(backgroundColor: Color(0xfffafafa)))
  52. I/flutter ( 6559): DecoratedBox(renderObject: RenderDecoratedBox)
  53. I/flutter ( 6559): NotificationListener<LayoutChangedNotification>()
  54. I/flutter ( 6559): _InkFeature([GlobalKey ink renderer]; renderObject: _RenderInkFeatures)
  55. I/flutter ( 6559): AnimatedDefaultTextStyle(duration: 200ms; inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 400; baseline: alphabetic; state: _AnimatedDefaultTextStyleState(427742350; ticker inactive))
  56. I/flutter ( 6559): DefaultTextStyle(inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 400; baseline: alphabetic)
  57. I/flutter ( 6559): Center(alignment: Alignment.center; renderObject: RenderPositionedBox)
  58. I/flutter ( 6559): FlatButton()
  59. I/flutter ( 6559): MaterialButton(state: _MaterialButtonState(398724090))
  60. I/flutter ( 6559): ConstrainedBox(BoxConstraints(88.0<=w<=Infinity, h=36.0); renderObject: RenderConstrainedBox relayoutBoundary=up1)
  61. I/flutter ( 6559): AnimatedDefaultTextStyle(duration: 200ms; inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 500; baseline: alphabetic; state: _AnimatedDefaultTextStyleState(315134664; ticker inactive))
  62. I/flutter ( 6559): DefaultTextStyle(inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 500; baseline: alphabetic)
  63. I/flutter ( 6559): IconTheme(color: Color(0xdd000000))
  64. I/flutter ( 6559): InkWell(state: _InkResponseState<InkResponse>(369160267))
  65. I/flutter ( 6559): GestureDetector()
  66. I/flutter ( 6559): RawGestureDetector(state: RawGestureDetectorState(175370983; gestures: tap; behavior: opaque))
  67. I/flutter ( 6559): _GestureSemantics(renderObject: RenderSemanticsGestureHandler relayoutBoundary=up2)
  68. I/flutter ( 6559): Listener(listeners: down; behavior: opaque; renderObject: RenderPointerListener relayoutBoundary=up3)
  69. I/flutter ( 6559): Container(padding: EdgeInsets(16.0, 0.0, 16.0, 0.0))
  70. I/flutter ( 6559): Padding(renderObject: RenderPadding relayoutBoundary=up4)
  71. I/flutter ( 6559): Center(alignment: Alignment.center; widthFactor: 1.0; renderObject: RenderPositionedBox relayoutBoundary=up5)
  72. I/flutter ( 6559): Text("Dump App")
  73. I/flutter ( 6559): RichText(renderObject: RenderParagraph relayoutBoundary=up6)

This is the “flattened” tree, showing all the widgets projectedthrough their various build functions. (This is the tree you obtain ifyou call toStringDeep() on the root of the widget tree.)You’ll see a lot of widgets in there that don’t appear in yourapplication’s source, because they are inserted by the framework’swidgets’ build functions. For example,InkFeature is an implementation detail of the Material widget.

Since the debugDumpApp() call is invoked when the button changesfrom being pressed to being released, it coincides with theFlatButton object calling setState()and thus marking itself dirty. That is why, when you look at the dump youshould see that specific object marked as “dirty”. You can also see whatgesture listeners have been registered; in this case, a singleGestureDetector is listed, and it is listening only to a “tap” gesture(“tap” is the output of a TapGestureDetector’s toStringShortfunction).

If you write your own widgets, you can add information by overridingdebugFillProperties(). Add [DiagnosticsProperty][[]objects to the method’s argument, and call the superclass method.This function is what the toString method uses to fill in thewidget’s description.

Render tree

If you are trying to debug a layout issue, then the Widgets layer’stree might be insufficiently detailed. In that case, you can dump therendering tree by calling debugDumpRenderTree().As with debugDumpApp(), you can call this more or less any timeexcept during a layout or paint phase. As a general rule,calling it from a frame callbackor an event handler is the best solution.

To call debugDumpRenderTree(), you need to add import'package:flutter/rendering.dart'; to your source file.

The output for the previous tiny example would look something likethe following:

  1. I/flutter ( 6559): RenderView
  2. I/flutter ( 6559): debug mode enabled - android
  3. I/flutter ( 6559): window size: Size(1080.0, 1794.0) (in physical pixels)
  4. I/flutter ( 6559): device pixel ratio: 2.625 (physical pixels per logical pixel)
  5. I/flutter ( 6559): configuration: Size(411.4, 683.4) at 2.625x (in logical pixels)
  6. I/flutter ( 6559):
  7. I/flutter ( 6559): └─child: RenderCustomPaint
  8. I/flutter ( 6559): creator: CustomPaint Banner CheckedModeBanner
  9. I/flutter ( 6559): WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)]
  10. I/flutter ( 6559): Theme AnimatedTheme ScrollConfiguration MaterialApp
  11. I/flutter ( 6559): [root]
  12. I/flutter ( 6559): parentData: <none>
  13. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  14. I/flutter ( 6559): size: Size(411.4, 683.4)
  15. I/flutter ( 6559):
  16. I/flutter ( 6559): └─child: RenderPointerListener
  17. I/flutter ( 6559): creator: Listener Navigator-[GlobalObjectKey<NavigatorState>
  18. I/flutter ( 6559): _WidgetsAppState(552902158)] Title LocaleQuery MediaQuery
  19. I/flutter ( 6559): DefaultTextStyle CustomPaint Banner CheckedModeBanner
  20. I/flutter ( 6559): WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)]
  21. I/flutter ( 6559): Theme AnimatedTheme
  22. I/flutter ( 6559): parentData: <none>
  23. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  24. I/flutter ( 6559): size: Size(411.4, 683.4)
  25. I/flutter ( 6559): behavior: defer-to-child
  26. I/flutter ( 6559): listeners: down, up, cancel
  27. I/flutter ( 6559):
  28. I/flutter ( 6559): └─child: RenderAbsorbPointer
  29. I/flutter ( 6559): creator: AbsorbPointer Listener
  30. I/flutter ( 6559): Navigator-[GlobalObjectKey<NavigatorState>
  31. I/flutter ( 6559): _WidgetsAppState(552902158)] Title LocaleQuery MediaQuery
  32. I/flutter ( 6559): DefaultTextStyle CustomPaint Banner CheckedModeBanner
  33. I/flutter ( 6559): WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)]
  34. I/flutter ( 6559): Theme
  35. I/flutter ( 6559): parentData: <none>
  36. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  37. I/flutter ( 6559): size: Size(411.4, 683.4)
  38. I/flutter ( 6559): absorbing: false
  39. I/flutter ( 6559):
  40. I/flutter ( 6559): └─child: RenderSemanticsAnnotations
  41. I/flutter ( 6559): creator: Semantics Focus-[GlobalKey 489139594] AbsorbPointer
  42. I/flutter ( 6559): Listener Navigator-[GlobalObjectKey<NavigatorState>
  43. I/flutter ( 6559): _WidgetsAppState(552902158)] Title LocaleQuery MediaQuery
  44. I/flutter ( 6559): DefaultTextStyle CustomPaint Banner CheckedModeBanner
  45. I/flutter ( 6559):
  46. I/flutter ( 6559): parentData: <none>
  47. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  48. I/flutter ( 6559): size: Size(411.4, 683.4)
  49. I/flutter ( 6559):
  50. I/flutter ( 6559): └─child: _RenderTheatre
  51. I/flutter ( 6559): creator: _Theatre Overlay-[GlobalKey 199833992] _FocusScope
  52. I/flutter ( 6559): Semantics Focus-[GlobalKey 489139594] AbsorbPointer
  53. I/flutter ( 6559): Listener Navigator-[GlobalObjectKey<NavigatorState>
  54. I/flutter ( 6559): _WidgetsAppState(552902158)] Title LocaleQuery MediaQuery
  55. I/flutter ( 6559): DefaultTextStyle
  56. I/flutter ( 6559): parentData: <none>
  57. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  58. I/flutter ( 6559): size: Size(411.4, 683.4)
  59. I/flutter ( 6559):
  60. I/flutter ( 6559): ├─onstage: RenderStack
  61. I/flutter ( 6559): creator: Stack _Theatre Overlay-[GlobalKey 199833992]
  62. I/flutter ( 6559): _FocusScope Semantics Focus-[GlobalKey 489139594]
  63. I/flutter ( 6559): AbsorbPointer Listener
  64. I/flutter ( 6559): Navigator-[GlobalObjectKey<NavigatorState>
  65. I/flutter ( 6559): _WidgetsAppState(552902158)] Title LocaleQuery MediaQuery
  66. I/flutter ( 6559):
  67. I/flutter ( 6559): parentData: not positioned; offset=Offset(0.0, 0.0)
  68. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  69. I/flutter ( 6559): size: Size(411.4, 683.4)
  70. I/flutter ( 6559):
  71. I/flutter ( 6559): ├─child 1: RenderIgnorePointer
  72. I/flutter ( 6559): creator: IgnorePointer _OverlayEntry-[GlobalKey 612888877]
  73. I/flutter ( 6559): Stack _Theatre Overlay-[GlobalKey 199833992] _FocusScope
  74. I/flutter ( 6559): Semantics Focus-[GlobalKey 489139594] AbsorbPointer
  75. I/flutter ( 6559): Listener Navigator-[GlobalObjectKey<NavigatorState>
  76. I/flutter ( 6559): _WidgetsAppState(552902158)] Title
  77. I/flutter ( 6559): parentData: not positioned; offset=Offset(0.0, 0.0)
  78. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  79. I/flutter ( 6559): size: Size(411.4, 683.4)
  80. I/flutter ( 6559): ignoring: false
  81. I/flutter ( 6559): ignoringSemantics: implicitly false
  82. I/flutter ( 6559):
  83. I/flutter ( 6559): └─child: RenderSemanticsAnnotations
  84. I/flutter ( 6559): creator: Semantics ModalBarrier IgnorePointer
  85. I/flutter ( 6559): _OverlayEntry-[GlobalKey 612888877] Stack _Theatre
  86. I/flutter ( 6559): Overlay-[GlobalKey 199833992] _FocusScope Semantics
  87. I/flutter ( 6559): Focus-[GlobalKey 489139594] AbsorbPointer Listener
  88. I/flutter ( 6559): parentData: <none>
  89. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  90. I/flutter ( 6559): size: Size(411.4, 683.4)
  91. I/flutter ( 6559):
  92. I/flutter ( 6559): └─child: RenderSemanticsGestureHandler
  93. I/flutter ( 6559): creator: _GestureSemantics RawGestureDetector GestureDetector
  94. I/flutter ( 6559): Semantics ModalBarrier IgnorePointer
  95. I/flutter ( 6559): _OverlayEntry-[GlobalKey 612888877] Stack _Theatre
  96. I/flutter ( 6559): Overlay-[GlobalKey 199833992] _FocusScope Semantics
  97. I/flutter ( 6559): parentData: <none>
  98. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  99. I/flutter ( 6559): size: Size(411.4, 683.4)
  100. I/flutter ( 6559):
  101. I/flutter ( 6559): └─child: RenderPointerListener
  102. I/flutter ( 6559): creator: Listener _GestureSemantics RawGestureDetector
  103. I/flutter ( 6559): GestureDetector Semantics ModalBarrier IgnorePointer
  104. I/flutter ( 6559): _OverlayEntry-[GlobalKey 612888877] Stack _Theatre
  105. I/flutter ( 6559): Overlay-[GlobalKey 199833992] _FocusScope
  106. I/flutter ( 6559): parentData: <none>
  107. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  108. I/flutter ( 6559): size: Size(411.4, 683.4)
  109. I/flutter ( 6559): behavior: opaque
  110. I/flutter ( 6559): listeners: down
  111. I/flutter ( 6559):
  112. I/flutter ( 6559): └─child: RenderConstrainedBox
  113. I/flutter ( 6559): creator: ConstrainedBox Listener _GestureSemantics
  114. I/flutter ( 6559): RawGestureDetector GestureDetector Semantics ModalBarrier
  115. I/flutter ( 6559): IgnorePointer _OverlayEntry-[GlobalKey 612888877] Stack
  116. I/flutter ( 6559): _Theatre Overlay-[GlobalKey 199833992]
  117. I/flutter ( 6559): parentData: <none>
  118. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  119. I/flutter ( 6559): size: Size(411.4, 683.4)
  120. I/flutter ( 6559): additionalConstraints: BoxConstraints(biggest)
  121. I/flutter ( 6559):
  122. I/flutter ( 6559): └─child 2: RenderSemanticsAnnotations
  123. I/flutter ( 6559): creator: Semantics Focus-[GlobalObjectKey
  124. I/flutter ( 6559): MaterialPageRoute<void>(875520219)] _ModalScope-[GlobalKey
  125. I/flutter ( 6559): 816151164] _OverlayEntry-[GlobalKey 727622716] Stack
  126. I/flutter ( 6559): _Theatre Overlay-[GlobalKey 199833992] _FocusScope
  127. I/flutter ( 6559): Semantics Focus-[GlobalKey 489139594] AbsorbPointer
  128. I/flutter ( 6559): Listener
  129. I/flutter ( 6559): parentData: not positioned; offset=Offset(0.0, 0.0)
  130. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  131. I/flutter ( 6559): size: Size(411.4, 683.4)
  132. I/flutter ( 6559):
  133. I/flutter ( 6559): └─child: RenderOffstage
  134. I/flutter ( 6559): creator: Offstage _FocusScope Semantics
  135. I/flutter ( 6559): Focus-[GlobalObjectKey MaterialPageRoute<void>(875520219)]
  136. I/flutter ( 6559): _ModalScope-[GlobalKey 816151164] _OverlayEntry-[GlobalKey
  137. I/flutter ( 6559): 727622716] Stack _Theatre Overlay-[GlobalKey 199833992]
  138. I/flutter ( 6559): _FocusScope Semantics Focus-[GlobalKey 489139594]
  139. I/flutter ( 6559): parentData: <none>
  140. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  141. I/flutter ( 6559): size: Size(411.4, 683.4)
  142. I/flutter ( 6559): offstage: false
  143. I/flutter ( 6559):
  144. I/flutter ( 6559): └─child: RenderIgnorePointer
  145. I/flutter ( 6559): creator: IgnorePointer Offstage _FocusScope Semantics
  146. I/flutter ( 6559): Focus-[GlobalObjectKey MaterialPageRoute<void>(875520219)]
  147. I/flutter ( 6559): _ModalScope-[GlobalKey 816151164] _OverlayEntry-[GlobalKey
  148. I/flutter ( 6559): 727622716] Stack _Theatre Overlay-[GlobalKey 199833992]
  149. I/flutter ( 6559): _FocusScope Semantics
  150. I/flutter ( 6559): parentData: <none>
  151. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  152. I/flutter ( 6559): size: Size(411.4, 683.4)
  153. I/flutter ( 6559): ignoring: false
  154. I/flutter ( 6559): ignoringSemantics: implicitly false
  155. I/flutter ( 6559):
  156. I/flutter ( 6559): └─child: RenderFractionalTranslation
  157. I/flutter ( 6559): creator: FractionalTranslation SlideTransition
  158. I/flutter ( 6559): _MountainViewPageTransition IgnorePointer Offstage
  159. I/flutter ( 6559): _FocusScope Semantics Focus-[GlobalObjectKey
  160. I/flutter ( 6559): MaterialPageRoute<void>(875520219)] _ModalScope-[GlobalKey
  161. I/flutter ( 6559): 816151164] _OverlayEntry-[GlobalKey 727622716] Stack
  162. I/flutter ( 6559): _Theatre
  163. I/flutter ( 6559): parentData: <none>
  164. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  165. I/flutter ( 6559): size: Size(411.4, 683.4)
  166. I/flutter ( 6559): translation: Offset(0.0, 0.0)
  167. I/flutter ( 6559): transformHitTests: true
  168. I/flutter ( 6559):
  169. I/flutter ( 6559): └─child: RenderRepaintBoundary
  170. I/flutter ( 6559): creator: RepaintBoundary FractionalTranslation
  171. I/flutter ( 6559): SlideTransition _MountainViewPageTransition IgnorePointer
  172. I/flutter ( 6559): Offstage _FocusScope Semantics Focus-[GlobalObjectKey
  173. I/flutter ( 6559): MaterialPageRoute<void>(875520219)] _ModalScope-[GlobalKey
  174. I/flutter ( 6559): 816151164] _OverlayEntry-[GlobalKey 727622716] Stack
  175. I/flutter ( 6559): parentData: <none>
  176. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  177. I/flutter ( 6559): size: Size(411.4, 683.4)
  178. I/flutter ( 6559): metrics: 83.3% useful (1 bad vs 5 good)
  179. I/flutter ( 6559): diagnosis: this is a useful repaint boundary and should be kept
  180. I/flutter ( 6559):
  181. I/flutter ( 6559): └─child: RenderDecoratedBox
  182. I/flutter ( 6559): creator: DecoratedBox Container AnimatedContainer Material
  183. I/flutter ( 6559): AppHome _ModalScopeStatus PageStorage-[GlobalKey
  184. I/flutter ( 6559): 619728754] RepaintBoundary FractionalTranslation
  185. I/flutter ( 6559): SlideTransition _MountainViewPageTransition IgnorePointer
  186. I/flutter ( 6559):
  187. I/flutter ( 6559): parentData: <none>
  188. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  189. I/flutter ( 6559): size: Size(411.4, 683.4)
  190. I/flutter ( 6559): decoration:
  191. I/flutter ( 6559): <no decorations specified>
  192. I/flutter ( 6559): configuration: ImageConfiguration(bundle:
  193. I/flutter ( 6559): PlatformAssetBundle@367106502(), devicePixelRatio: 2.625,
  194. I/flutter ( 6559): platform: android)
  195. I/flutter ( 6559):
  196. I/flutter ( 6559): └─child: RenderDecoratedBox
  197. I/flutter ( 6559): creator: DecoratedBox Container DecoratedBox Container
  198. I/flutter ( 6559): AnimatedContainer Material AppHome _ModalScopeStatus
  199. I/flutter ( 6559): PageStorage-[GlobalKey 619728754] RepaintBoundary
  200. I/flutter ( 6559): FractionalTranslation SlideTransition
  201. I/flutter ( 6559): parentData: <none>
  202. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  203. I/flutter ( 6559): size: Size(411.4, 683.4)
  204. I/flutter ( 6559): decoration:
  205. I/flutter ( 6559): backgroundColor: Color(0xfffafafa)
  206. I/flutter ( 6559): configuration: ImageConfiguration(bundle:
  207. I/flutter ( 6559): PlatformAssetBundle@367106502(), devicePixelRatio: 2.625,
  208. I/flutter ( 6559): platform: android)
  209. I/flutter ( 6559):
  210. I/flutter ( 6559): └─child: _RenderInkFeatures
  211. I/flutter ( 6559): creator: _InkFeature-[GlobalKey ink renderer]
  212. I/flutter ( 6559): NotificationListener<LayoutChangedNotification> DecoratedBox
  213. I/flutter ( 6559): Container DecoratedBox Container AnimatedContainer
  214. I/flutter ( 6559): Material AppHome _ModalScopeStatus PageStorage-[GlobalKey
  215. I/flutter ( 6559): 619728754] RepaintBoundary
  216. I/flutter ( 6559): parentData: <none>
  217. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  218. I/flutter ( 6559): size: Size(411.4, 683.4)
  219. I/flutter ( 6559):
  220. I/flutter ( 6559): └─child: RenderPositionedBox
  221. I/flutter ( 6559): creator: Center DefaultTextStyle AnimatedDefaultTextStyle
  222. I/flutter ( 6559): _InkFeature-[GlobalKey ink renderer]
  223. I/flutter ( 6559): NotificationListener<LayoutChangedNotification> DecoratedBox
  224. I/flutter ( 6559): Container DecoratedBox Container AnimatedContainer
  225. I/flutter ( 6559): Material AppHome
  226. I/flutter ( 6559): parentData: <none>
  227. I/flutter ( 6559): constraints: BoxConstraints(w=411.4, h=683.4)
  228. I/flutter ( 6559): size: Size(411.4, 683.4)
  229. I/flutter ( 6559): alignment: Alignment.center
  230. I/flutter ( 6559): widthFactor: expand
  231. I/flutter ( 6559): heightFactor: expand
  232. I/flutter ( 6559):
  233. I/flutter ( 6559): └─child: RenderConstrainedBox relayoutBoundary=up1
  234. I/flutter ( 6559): creator: ConstrainedBox MaterialButton FlatButton Center
  235. I/flutter ( 6559): DefaultTextStyle AnimatedDefaultTextStyle
  236. I/flutter ( 6559): _InkFeature-[GlobalKey ink renderer]
  237. I/flutter ( 6559): NotificationListener<LayoutChangedNotification> DecoratedBox
  238. I/flutter ( 6559): Container DecoratedBox Container
  239. I/flutter ( 6559): parentData: offset=Offset(156.7, 323.7)
  240. I/flutter ( 6559): constraints: BoxConstraints(0.0<=w<=411.4, 0.0<=h<=683.4)
  241. I/flutter ( 6559): size: Size(98.0, 36.0)
  242. I/flutter ( 6559): additionalConstraints: BoxConstraints(88.0<=w<=Infinity, h=36.0)
  243. I/flutter ( 6559):
  244. I/flutter ( 6559): └─child: RenderSemanticsGestureHandler relayoutBoundary=up2
  245. I/flutter ( 6559): creator: _GestureSemantics RawGestureDetector GestureDetector
  246. I/flutter ( 6559): InkWell IconTheme DefaultTextStyle
  247. I/flutter ( 6559): AnimatedDefaultTextStyle ConstrainedBox MaterialButton
  248. I/flutter ( 6559): FlatButton Center DefaultTextStyle
  249. I/flutter ( 6559): parentData: <none>
  250. I/flutter ( 6559): constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
  251. I/flutter ( 6559): size: Size(98.0, 36.0)
  252. I/flutter ( 6559):
  253. I/flutter ( 6559): └─child: RenderPointerListener relayoutBoundary=up3
  254. I/flutter ( 6559): creator: Listener _GestureSemantics RawGestureDetector
  255. I/flutter ( 6559): GestureDetector InkWell IconTheme DefaultTextStyle
  256. I/flutter ( 6559): AnimatedDefaultTextStyle ConstrainedBox MaterialButton
  257. I/flutter ( 6559): FlatButton Center
  258. I/flutter ( 6559): parentData: <none>
  259. I/flutter ( 6559): constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
  260. I/flutter ( 6559): size: Size(98.0, 36.0)
  261. I/flutter ( 6559): behavior: opaque
  262. I/flutter ( 6559): listeners: down
  263. I/flutter ( 6559):
  264. I/flutter ( 6559): └─child: RenderPadding relayoutBoundary=up4
  265. I/flutter ( 6559): creator: Padding Container Listener _GestureSemantics
  266. I/flutter ( 6559): RawGestureDetector GestureDetector InkWell IconTheme
  267. I/flutter ( 6559): DefaultTextStyle AnimatedDefaultTextStyle ConstrainedBox
  268. I/flutter ( 6559): MaterialButton
  269. I/flutter ( 6559): parentData: <none>
  270. I/flutter ( 6559): constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
  271. I/flutter ( 6559): size: Size(98.0, 36.0)
  272. I/flutter ( 6559): padding: EdgeInsets(16.0, 0.0, 16.0, 0.0)
  273. I/flutter ( 6559):
  274. I/flutter ( 6559): └─child: RenderPositionedBox relayoutBoundary=up5
  275. I/flutter ( 6559): creator: Center Padding Container Listener
  276. I/flutter ( 6559): _GestureSemantics RawGestureDetector GestureDetector
  277. I/flutter ( 6559): InkWell IconTheme DefaultTextStyle
  278. I/flutter ( 6559): AnimatedDefaultTextStyle ConstrainedBox
  279. I/flutter ( 6559): parentData: offset=Offset(16.0, 0.0)
  280. I/flutter ( 6559): constraints: BoxConstraints(56.0<=w<=379.4, h=36.0)
  281. I/flutter ( 6559): size: Size(66.0, 36.0)
  282. I/flutter ( 6559): alignment: Alignment.center
  283. I/flutter ( 6559): widthFactor: 1.0
  284. I/flutter ( 6559): heightFactor: expand
  285. I/flutter ( 6559):
  286. I/flutter ( 6559): └─child: RenderParagraph relayoutBoundary=up6
  287. I/flutter ( 6559): creator: RichText Text Center Padding Container
  288. I/flutter ( 6559): Listener _GestureSemantics RawGestureDetector
  289. I/flutter ( 6559): GestureDetector InkWell IconTheme DefaultTextStyle
  290. I/flutter ( 6559): parentData: offset=Offset(0.0, 10.0)
  291. I/flutter ( 6559): constraints: BoxConstraints(0.0<=w<=379.4, 0.0<=h<=36.0)
  292. I/flutter ( 6559): size: Size(66.0, 16.0)
  293. I/flutter ( 6559): ╘═╦══ text ═══
  294. I/flutter ( 6559): TextSpan:
  295. I/flutter ( 6559): inherit: false
  296. I/flutter ( 6559): color: Color(0xdd000000)
  297. I/flutter ( 6559): family: "Roboto"
  298. I/flutter ( 6559): size: 14.0
  299. I/flutter ( 6559): weight: 500
  300. I/flutter ( 6559): baseline: alphabetic
  301. I/flutter ( 6559): "Dump App"
  302. I/flutter ( 6559): ╚═══════════
  303. I/flutter ( 6559):
  304. I/flutter ( 6559): └╌no offstage children

This is the output of the root RenderObject object’stoStringDeep() function.

When debugging layout issues, the key fields to look at are thesize and constraints fields. The constraints flow down the tree,and the sizes flow back up.

For example, in the previous dump you can see that the window size,Size(411.4, 683.4), is used to force all the boxes down to theRenderPositionedBox to be the size of the screen, withconstraints of BoxConstraints(w=411.4, h=683.4).The RenderPositionedBox, which the dump says was created by aCenter widget (as described by the creator field),sets its child’s constraints to a loose version of this:BoxConstraints(0.0<=w<=411.4, 0.0<=h<=683.4). The child, aRenderPadding, further inserts these constraints to ensurethere is room for the padding, and thus the [RenderConstrainedBox][]has a loose constraint of BoxConstraints(0.0<=w<=395.4,0.0<=h<=667.4). This object, which the creator field tells us isprobably part of the [FlatButton][]'s definition,sets a minimum width of 88 pixels on its contents and aspecific height of 36.0. (This is the FlatButton` class implementingthe Material Design guidelines regarding button dimensions.)

The inner-most RenderPositionedBox loosens the constraints again,this time to center the text within the button. TheRenderParagraph picks its size based on its contents.If you now follow the sizes back up the chain,you’ll see how the text’s size is what influences thewidth of all the boxes that form the button, as they all take theirchild’s dimensions to size themselves.

Another way to notice this is by looking at the “relayoutSubtreeRoot”part of the descriptions of each box, which essentially tells you howmany ancestors depend on this element’s size in some way.Thus the RenderParagraph has a relayoutSubtreeRoot=up8,meaning that when the RenderParagraph is dirtied,eight ancestors also have to be dirtied because they might beaffected by the new dimensions.

If you write your own render objects, you can add information to thedump by overriding debugFillProperties().Add DiagnosticsPropertyobjects to the method’s argument, and call the superclass method.

Layer tree

If you are trying to debug a compositing issue, you can usedebugDumpLayerTree().For the previous example, it would output:

  1. I/flutter : TransformLayer
  2. I/flutter : creator: [root]
  3. I/flutter : offset: Offset(0.0, 0.0)
  4. I/flutter : transform:
  5. I/flutter : [0] 3.5,0.0,0.0,0.0
  6. I/flutter : [1] 0.0,3.5,0.0,0.0
  7. I/flutter : [2] 0.0,0.0,1.0,0.0
  8. I/flutter : [3] 0.0,0.0,0.0,1.0
  9. I/flutter :
  10. I/flutter : ├─child 1: OffsetLayer
  11. 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
  12. I/flutter : offset: Offset(0.0, 0.0)
  13. I/flutter :
  14. I/flutter : └─child 1: PictureLayer
  15. I/flutter :
  16. I/flutter : └─child 2: PictureLayer

This is the output of calling toStringDeep on the root Layer object.

The transform at the root is the transform that applies the devicepixel ratio; in this case, a ratio of 3.5 device pixels for everylogical pixel.

The RepaintBoundary widget, which creates a RenderRepaintBoundaryin the render tree, creates a new layer in the layer tree. This isused to reduce how much needs to be repainted.

Semantics tree

You can also obtain a dump of the Semantics tree(the tree presented to the system accessibility APIs) usingdebugDumpSemanticsTree(). To use this,you have to have first enable accessibility, for example, byenabling a system accessibility tool or the SemanticsDebugger.

For the previous example, it would output the following:

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

Scheduling

To find out where your events happen relative to the frame’sbegin/end, you can toggle the debugPrintBeginFrameBannerand the debugPrintEndFrameBanner booleans to print thebeginning and end of the frames to the console.

For example:

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

The debugPrintScheduleFrameStacks flag can also be usedto print the call stack causing the current frame to be scheduled.

Debug flags: layout

You can also debug a layout problem visually, by settingdebugPaintSizeEnabled to true.This is a boolean from the rendering library. It can beenabled at any time and affects all painting while it is true.The easiest way to set it is at the top of your void main()entry point. See an example in the following code:

  1. //add import to rendering library
  2. import 'package:flutter/rendering.dart';
  3. void main() {
  4. debugPaintSizeEnabled=true;
  5. runApp(MyApp());
  6. }

When it is enabled, all boxes get a bright teal border,padding (from widgets like Padding) is shown in fadedblue with a darker blue box around the child, alignment(from widgets like Center and Align) is shown withyellow arrows, and spacers (from widgets likeContainer when they have no child) are shown in gray.

The debugPaintBaselinesEnabled flagdoes something similar but for objects with baselines.The alphabetic baseline is shown in bright green and theideographic baseline in orange.

The debugPaintPointersEnabled flag turns on aspecial mode whereby any objects that are being tappedget highlighted in teal. This can help you determinewhether an object is somehow failing to correctly hittest (which might happen if, for instance, it is actuallyoutside the bounds of its parent and thus notbeing considered for hit testing in the first place).

If you’re trying to debug compositor layers, for exampleto determine whether and where to add RepaintBoundarywidgets, you can use the debugPaintLayerBordersEnabledflag, which outlines each layer’s bounds in orange,or the debugRepaintRainbowEnabled flag,which causes layers to be overlayed with a rotating set ofcolors whenever they are repainted.

All of these flags only work in debug mode.In general, anything in the Flutter framework that starts with“debug…” only works in debug mode.

Debugging animations

备忘 The easiest way to debug animations is to slow them down. You can do this using the Slow Animations button in DevTools’ Inspector view, which slows down the animation by 5x. If you want more control over the amount of slowness, use the following instructions.

Set the timeDilation variable (from the schedulerlibrary) to a number greater than 1.0, for instance, 50.0.It’s best to only set this once on app startup. If youchange it on the fly, especially if you reduce it whileanimations are running, it’s possible that the frameworkwill observe time going backwards, which will probablyresult in asserts and generally interfere with your efforts.

Debug flags: performance

备忘 You can achieve similar results to some of these debug flags using DevTools. Some of the debug flags aren’t particularly useful. If you find a flag that has functionality you would like to see added to DevTools, please file an issue.

Flutter provides a wide variety of debug flags and functionsto help you debug your app at various points along thedevelopment cycle. To use these features, you must compilein debug mode. The following list, while not complete,highlights some of flags (and one function) from therendering library for debugging performance issues.

You can set these flags either by editing the framework code,or by importing the module and setting the value in yourmain() method, following by a hot restart.

  • debugDumpRenderTree()
  • Call this function when not in a layout or repaint phase to dump the rendering tree to the console. (Pressing t from flutter run calls this command.) Search for “RepaintBoundary” to see diagnostics on how useful a boundary is.

  • debugPaintLayerBordersEnabled

  • PENDING

  • debugRepaintRainbowEnabled

  • You can enable this flag in the Flutter inspector by selecting the Repaint Rainbow button. If any static widgets are rotating through the colors of the rainbow (for example, a static header), those areas are candidates for adding repaint boundaries.

  • debugPrintMarkNeedsLayoutStacks

  • Enable this flag if you’re seeing more layouts than you expect (for example, on the timeline, on a profile, or from a print statement inside a layout method). Once enabled, the console is flooded with stack traces showing why each render object is being marked dirty for layout. You can use the debugPrintStack() method from the services library to print your own stack traces on demand, if this kind of approach is useful to you.

  • debugPrintMarkNeedsPaintStacks

  • Similar to debugPrintMarkNeedsLayoutStacks, but for excess painting. You can use the debugPrintStack() method from the services library to print your own stack traces on demand, if this kind of approach is useful to you.

Tracing Dart code performance

备忘 You can use the DevTools Timeline view to perform traces. You can also import and export trace files into the Timeline view, but only files generated by DevTools.

To perform custom performance traces programmatically andmeasure wall/CPU time of arbitrary segments of Dart codesimilar to what would be done on Android with systrace,use dart:developer Timeline utilities to wrap thecode you want to measure such as:

  1. import 'dart:developer';
  2. Timeline.startSync('interesting function');
  3. // iWonderHowLongThisTakes();
  4. Timeline.finishSync();

Then open your app’s Observatory’s timeline page, check the ‘Dart’recording option and perform the function you want to measure.

Refreshing the page displays the chronological timeline recordsof your app in Chrome’s tracing tool.

Be sure to run your app in profile mode to ensure that theruntime performance characteristics closely match that of yourfinal product.

Performance overlay

备忘 You can toggle display of the performance overlay on your app using the Performance Overlay button in the Flutter inspector. If you prefer to do it in code, use the following instructions.

You can programmatically enable the PerformanceOverlay widget bysetting the showPerformanceOverlay property to true on theMaterialApp, CupertinoApp, or WidgetsAppconstructor:

  1. class MyApp extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return MaterialApp(
  5. showPerformanceOverlay: true,
  6. title: 'My Awesome App',
  7. theme: ThemeData(
  8. primarySwatch: Colors.blue,
  9. ),
  10. home: MyHomePage(title: 'My Awesome App'),
  11. );
  12. }
  13. }

(If you’re not using MaterialApp, CupertinoApp,or WidgetsApp, you can get the same effect by wrapping yourapplication in a stack and putting a widget on your stack that wascreated by calling PerformanceOverlay.allEnabled().)

For information on how to interpret the graphs in the overlay,see The performance overlay inProfiling Flutter performance.

Widget alignment grid

You can programmatically overlay aMaterial Design baseline grid on top of your app tohelp verify alignments by using thedebugShowMaterialGrid argument in theMaterialApp constructor.

In non-Material applications, you can achieve a similareffect by using a GridPaper widget directly.