# Debug Flutter apps from code > How to enable various debugging tools from your code and at the command line. This guide describes which debugging features you can enable in your code. For a full list of debugging and profiling tools, check out the [Debugging][] page. ## Add logging to your application The following list contains a few statements that you can use to log the behavior of your application. You can view your logs in DevTools' [Logging view][] or in your system console. * [`print()`][]: Prints a `stdout` (standard output) message. Part of the `dart:io` library. * [`stderr.method_to_invoke()`][]: Prints a `stderr` (standard error) message. Replace `method_to_invoke()` with a method supported by the `stderr` property, such as `writeln()` or `write()`. Often used in a `try...catch` block. Part of the `dart:io` library. ```dart stderr.writeln('print me'); ``` * [`log()`][]: Includes greater granularity and more information in the logging output. Part of the `dart:developer` library. * [`debugPrint()`][]: If too much output results in discarded log lines, use this to keep those lines. Will print messages in release mode unless part of a debug mode check or an assert. Part of the `foundations` library. ### Example 1 {:.no_toc} ```dart import 'dart:developer' as developer; void main() { developer.log('log me', name: 'my.app.category'); developer.log('log me 1', name: 'my.other.category'); developer.log('log me 2', name: 'my.other.category'); } ``` You can also pass app data to the log call. The convention for this is to use the `error:` named parameter on the `log()` call, JSON encode the object you want to send, and pass the encoded string to the error parameter. ### Example 2 {:.no_toc} ```dart import 'dart:convert'; import 'dart:developer' as developer; void main() { var myCustomObject = MyCustomObject(); developer.log( 'log me', name: 'my.app.category', error: jsonEncode(myCustomObject), ); } ``` DevTool's logging view interprets the JSON encoded error parameter as a data object. DevTool renders in the details view for that log entry. ## Set breakpoints You can set breakpoints in DevTools' [Debugger][] or in the built-in debugger of your IDE. To set programmatic breakpoints: 1. Import the `dart:developer` package into the relevant file. 1. Insert programmatic breakpoints using the `debugger()` statement. This statement takes an optional `when` argument. This boolean argument sets a break when the given condition resolves to true. **Example 3** illustrates this. ### Example 3 {:.no_toc} ```dart import 'dart:developer'; void someFunction(double offset) { debugger(when: offset > 30); // ... } ``` ## Debug app layers using flags Each layer of the Flutter framework provides a function to dump its current state or events to the console using the `debugPrint` property. :::note All of the following examples were run as macOS native apps on a MacBook Pro M1. These will differ from any dumps your development machine prints. ::: :::tip Each render object in any tree includes the first five hexadecimal digits of its [`hashCode`][]. This hash serves as a unique identifier for that render object. ::: [`hashCode`]: https://api.flutter.dev/flutter/rendering/TextSelectionPoint/hashCode.html ### Print the widget tree To dump the state of the Widgets library, call the [`debugDumpApp()`][] function. 1. Open your source file. 1. Import `package:flutter/rendering.dart`. 1. Call the [`debugDumpApp()`][] function from within the `runApp()` function. You need your app in debug mode. You cannot call this function inside a `build()` method when the app is building. 1. If you haven't started your app, debug it using your IDE. 1. If you have started your app, save your source file. Hot reload re-renders your app. #### Example 4: Call `debugDumpApp()` ```dart import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp(home: AppHome())); } class AppHome extends StatelessWidget { const AppHome({super.key}); @override Widget build(BuildContext context) { return Material( child: Center( child: TextButton( onPressed: () { debugDumpApp(); }, child: const Text('Dump Widget Tree'), ), ), ); } } ``` This function recursively calls the `toStringDeep()` method starting with the root of the widget tree. It returns a "flattened" tree. **Example 4** produces the following widget tree. It includes: * All the widgets projected through their various build functions. * Many widgets that don't appear in your app's source. The framework's widgets' build functions insert them during the build. The following tree, for example, shows [`_InkFeatures`][]. That class implements part of the [`Material`][] widget. It doesn't appear anywhere in the code in **Example 4**.
Expand to view the widget tree for Example 4 ```plaintext flutter: WidgetsFlutterBinding - DEBUG MODE flutter: [root](renderObject: RenderView#06beb) flutter: └View-[GlobalObjectKey FlutterView#7971c] flutter: └_ViewScope flutter: └_MediaQueryFromView(state: _MediaQueryFromViewState#d790c) flutter: └MediaQuery(MediaQueryData(size: Size(800.0, 600.0), devicePixelRatio: 1.0, textScaleFactor: 1.0, platformBrightness: Brightness.dark, padding: EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, systemGestureInsets: EdgeInsets.zero, alwaysUse24HourFormat: false, accessibleNavigation: false, highContrast: false, disableAnimations: false, invertColors: false, boldText: false, navigationMode: traditional, gestureSettings: DeviceGestureSettings(touchSlop: null), displayFeatures: [])) flutter: └MaterialApp(state: _MaterialAppState#27fa9) flutter: └ScrollConfiguration(behavior: MaterialScrollBehavior) flutter: └HeroControllerScope flutter: └Focus(state: _FocusState#d7f97) flutter: └_FocusInheritedScope flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#a6464) flutter: └WidgetsApp-[GlobalObjectKey _MaterialAppState#27fa9](state: _WidgetsAppState#b5b17) flutter: └RootRestorationScope(state: _RootRestorationScopeState#6b028) flutter: └UnmanagedRestorationScope flutter: └RestorationScope(dependencies: [UnmanagedRestorationScope], state: _RestorationScopeState#d1369) flutter: └UnmanagedRestorationScope flutter: └SharedAppData(state: _SharedAppDataState#95e82) flutter: └_SharedAppModel flutter: └Shortcuts(shortcuts: , state: _ShortcutsState#272dc) flutter: └Focus(debugLabel: "Shortcuts", dependencies: [_FocusInheritedScope], state: _FocusState#a3300) flutter: └_FocusInheritedScope flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#db110) flutter: └DefaultTextEditingShortcuts flutter: └Shortcuts(shortcuts: , state: _ShortcutsState#1d796) flutter: └Focus(debugLabel: "Shortcuts", dependencies: [_FocusInheritedScope], state: _FocusState#0081b) flutter: └_FocusInheritedScope flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#0d70e) flutter: └Shortcuts(shortcuts: , state: _ShortcutsState#56bac) flutter: └Focus(debugLabel: "Shortcuts", dependencies: [_FocusInheritedScope], state: _FocusState#3152e) flutter: └_FocusInheritedScope flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#b7eaf) flutter: └Actions(dispatcher: null, actions: {DoNothingIntent: DoNothingAction#0fda1, DoNothingAndStopPropagationIntent: DoNothingAction#17f30, RequestFocusIntent: RequestFocusAction#10bd0, NextFocusIntent: NextFocusAction#60317, PreviousFocusIntent: PreviousFocusAction#2a933, DirectionalFocusIntent: DirectionalFocusAction#a6922, ScrollIntent: _OverridableContextAction#964fe(defaultAction: ScrollAction#ffb50), PrioritizedIntents: PrioritizedAction#be0e2, VoidCallbackIntent: VoidCallbackAction#805fa}, state: _ActionsState#bbd25) flutter: └_ActionsScope flutter: └FocusTraversalGroup(policy: ReadingOrderTraversalPolicy#f1e76, state: _FocusTraversalGroupState#0c200) flutter: └Focus(debugLabel: "FocusTraversalGroup", focusNode: _FocusTraversalGroupNode#ffcad(FocusTraversalGroup [IN FOCUS PATH]), dependencies: [_FocusInheritedScope], state: _FocusState#c7dc2) flutter: └_FocusInheritedScope flutter: └TapRegionSurface(renderObject: RenderTapRegionSurface#17aba) flutter: └ShortcutRegistrar(state: _ShortcutRegistrarState#44954) flutter: └_ShortcutRegistrarScope flutter: └Shortcuts(manager: ShortcutManager#eb38c(shortcuts: {}), shortcuts: {}, state: _ShortcutsState#f85ac) flutter: └Focus(debugLabel: "Shortcuts", dependencies: [_FocusInheritedScope], state: _FocusState#8c1a7) flutter: └_FocusInheritedScope flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#1fc98) flutter: └Localizations(locale: en_US, delegates: [DefaultMaterialLocalizations.delegate(en_US), DefaultCupertinoLocalizations.delegate(en_US), DefaultWidgetsLocalizations.delegate(en_US)], state: _LocalizationsState#ae3a0) flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, textDirection: ltr, renderObject: RenderSemanticsAnnotations#8776e) flutter: └_LocalizationsScope-[GlobalKey#61ca6] flutter: └Directionality(textDirection: ltr) flutter: └Title(color: Color(0xff2196f3)) flutter: └CheckedModeBanner("DEBUG") flutter: └Banner("DEBUG", textDirection: ltr, location: topEnd, Color(0xa0b71c1c), text inherit: true, text color: Color(0xffffffff), text size: 10.2, text weight: 900, text height: 1.0x, dependencies: [Directionality]) flutter: └CustomPaint(renderObject: RenderCustomPaint#c014d) flutter: └DefaultTextStyle(debugLabel: fallback style; consider putting your text in a Material, inherit: true, color: Color(0xd0ff0000), family: monospace, size: 48.0, weight: 900, decoration: double Color(0xffffff00) TextDecoration.underline, softWrap: wrapping at box width, overflow: clip) flutter: └Builder(dependencies: [MediaQuery]) flutter: └ScaffoldMessenger(dependencies: [MediaQuery], state: ScaffoldMessengerState#5b36e) flutter: └_ScaffoldMessengerScope flutter: └DefaultSelectionStyle flutter: └AnimatedTheme(duration: 200ms, state: _AnimatedThemeState#cd149(ticker inactive, ThemeDataTween(ThemeData#ef3b2 → ThemeData#ef3b2))) flutter: └Theme(ThemeData#ef3b2, dependencies: [DefaultSelectionStyle]) flutter: └_InheritedTheme flutter: └CupertinoTheme(brightness: light, primaryColor: MaterialColor(primary value: Color(0xff2196f3)), primaryContrastingColor: Color(0xffffffff), scaffoldBackgroundColor: Color(0xfffafafa), actionTextStyle: TextStyle(inherit: false, color: MaterialColor(primary value: Color(0xff2196f3)), family: .SF Pro Text, size: 17.0, letterSpacing: -0.4, decoration: TextDecoration.none), navActionTextStyle: TextStyle(inherit: false, color: MaterialColor(primary value: Color(0xff2196f3)), family: .SF Pro Text, size: 17.0, letterSpacing: -0.4, decoration: TextDecoration.none)) flutter: └_InheritedCupertinoTheme flutter: └IconTheme(color: MaterialColor(primary value: Color(0xff2196f3))) flutter: └IconTheme(color: Color(0xdd000000)) flutter: └DefaultSelectionStyle flutter: └FocusScope(debugLabel: "Navigator Scope", AUTOFOCUS, dependencies: [_FocusInheritedScope], state: _FocusScopeState#acbd8) flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#ab3f0) flutter: └_FocusInheritedScope flutter: └Navigator-[GlobalObjectKey _WidgetsAppState#b5b17](dependencies: [HeroControllerScope, UnmanagedRestorationScope], state: NavigatorState#1395a(tickers: tracking 1 ticker)) flutter: └HeroControllerScope flutter: └Listener(listeners: [down, up, cancel], behavior: deferToChild, renderObject: RenderPointerListener#34172) flutter: └AbsorbPointer(absorbing: false, renderObject: RenderAbsorbPointer#f8711) flutter: └FocusTraversalGroup(policy: ReadingOrderTraversalPolicy#f1e76, state: _FocusTraversalGroupState#8d61a) flutter: └Focus(debugLabel: "FocusTraversalGroup", focusNode: _FocusTraversalGroupNode#dd2b1(FocusTraversalGroup [IN FOCUS PATH]), dependencies: [_FocusInheritedScope], state: _FocusState#0bb03) flutter: └_FocusInheritedScope flutter: └Focus(debugLabel: "Navigator", AUTOFOCUS, focusNode: FocusNode#a3309(Navigator [IN FOCUS PATH]), dependencies: [_FocusInheritedScope], state: _FocusState#d3d07) flutter: └_FocusInheritedScope flutter: └UnmanagedRestorationScope flutter: └Overlay-[LabeledGlobalKey#5485a](state: OverlayState#5bd52(entries: [OverlayEntry#fc947(opaque: true; maintainState: false), OverlayEntry#05a32(opaque: false; maintainState: true)])) flutter: └_Theater(skipCount: 0, dependencies: [Directionality], renderObject: _RenderTheater#e86c3) flutter: ├_OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#1b37e](state: _OverlayEntryWidgetState#06ab0) flutter: │└TickerMode(state: _TickerModeState#0b4ac(requested mode: enabled)) flutter: │ └_EffectiveTickerMode(effective mode: enabled) flutter: │ └_RenderTheaterMarker flutter: │ └IgnorePointer(ignoring: false, renderObject: RenderIgnorePointer#34c66) flutter: │ └ModalBarrier flutter: │ └BlockSemantics(blocking: true, renderObject: RenderBlockSemantics#97799) flutter: │ └ExcludeSemantics(excluding: true, renderObject: RenderExcludeSemantics#8c4ce) flutter: │ └_ModalBarrierGestureDetector flutter: │ └RawGestureDetector(state: RawGestureDetectorState#556f6(gestures: [any tap], behavior: opaque)) flutter: │ └_GestureSemantics(renderObject: RenderSemanticsGestureHandler#616f1) flutter: │ └Listener(listeners: [down, panZoomStart], behavior: opaque, renderObject: RenderPointerListener#c2b89) flutter: │ └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#c3b31) flutter: │ └MouseRegion(listeners: , cursor: SystemMouseCursor(basic), renderObject: RenderMouseRegion#53cdb) flutter: │ └ConstrainedBox(BoxConstraints(biggest), renderObject: RenderConstrainedBox#faa51) flutter: └_OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#bc0aa](state: _OverlayEntryWidgetState#cbf35) flutter: └TickerMode(state: _TickerModeState#23e73(requested mode: enabled)) flutter: └_EffectiveTickerMode(effective mode: enabled) flutter: └_RenderTheaterMarker flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, sortKey: OrdinalSortKey#135f4(order: 0.0), renderObject: RenderSemanticsAnnotations#5565e) flutter: └_ModalScope-[LabeledGlobalKey<_ModalScopeState>#4fe82](state: _ModalScopeState#4da7d) flutter: └AnimatedBuilder(listenable: ValueNotifier#d87c6(null), state: _AnimatedState#dde81) flutter: └RestorationScope(dependencies: [UnmanagedRestorationScope], state: _RestorationScopeState#78c51) flutter: └UnmanagedRestorationScope flutter: └_ModalScopeStatus(active) flutter: └Offstage(offstage: false, renderObject: RenderOffstage#5e498) flutter: └PageStorage flutter: └Builder flutter: └Actions(dispatcher: null, actions: {DismissIntent: _DismissModalAction#6279e}, state: _ActionsState#48019) flutter: └_ActionsScope flutter: └PrimaryScrollController(ScrollController#6a546(no clients)) flutter: └FocusScope(debugLabel: "_ModalScopeState Focus Scope", focusNode: FocusScopeNode#0e2af(_ModalScopeState Focus Scope [PRIMARY FOCUS]), dependencies: [_FocusInheritedScope], state: _FocusScopeState#0bac4) flutter: └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#44b4e) flutter: └_FocusInheritedScope flutter: └RepaintBoundary(renderObject: RenderRepaintBoundary#38f41) flutter: └AnimatedBuilder(listenable: Listenable.merge([AnimationController#9d623(⏭ 1.000; paused; for MaterialPageRoute(/))➩ProxyAnimation, kAlwaysDismissedAnimation➩ProxyAnimation➩ProxyAnimation]), dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#61ca6]], state: _AnimatedState#47725) flutter: └CupertinoPageTransition(dependencies: [Directionality]) flutter: └SlideTransition(listenable: kAlwaysDismissedAnimation➩ProxyAnimation➩ProxyAnimation➩Cubic(0.35, 0.91, 0.33, 0.97)ₒₙ/Cubic(0.67, 0.03, 0.65, 0.09)➩Tween(Offset(0.0, 0.0) → Offset(-0.3, 0.0))➩Offset(0.0, 0.0), state: _AnimatedState#b6162) flutter: └FractionalTranslation(renderObject: RenderFractionalTranslation#fb461) flutter: └SlideTransition(listenable: AnimationController#9d623(⏭ 1.000; paused; for MaterialPageRoute(/))➩ProxyAnimation➩ThreePointCubic ₒₙ/FlippedCurve(ThreePointCubic )➩Tween(Offset(1.0, 0.0) → Offset(0.0, 0.0))➩Offset(0.0, 0.0), state: _AnimatedState#834bf) flutter: └FractionalTranslation(renderObject: RenderFractionalTranslation#73ea4) flutter: └DecoratedBoxTransition(listenable: AnimationController#9d623(⏭ 1.000; paused; for MaterialPageRoute(/))➩ProxyAnimation➩Cubic(0.35, 0.91, 0.33, 0.97)➩DecorationTween(_CupertinoEdgeShadowDecoration(colors: null) → _CupertinoEdgeShadowDecoration(colors: [Color(0x04000000), Color(0x00000000)]))➩_CupertinoEdgeShadowDecoration(colors: [Color(0x04000000), Color(0x00000000)]), state: _AnimatedState#a7fca) flutter: └DecoratedBox(bg: _CupertinoEdgeShadowDecoration(colors: [Color(0x04000000), Color(0x00000000)]), dependencies: [Directionality, MediaQuery, _LocalizationsScope-[GlobalKey#61ca6]], renderObject: RenderDecoratedBox#9965c) flutter: └_CupertinoBackGestureDetector(dependencies: [Directionality, MediaQuery], state: _CupertinoBackGestureDetectorState#ab8cd) flutter: └Stack(alignment: AlignmentDirectional.topStart, fit: passthrough, dependencies: [Directionality], renderObject: RenderStack#b2b7c) flutter: ├AnimatedBuilder(listenable: ValueNotifier#1a88e(false), state: _AnimatedState#6e33c) flutter: │└IgnorePointer(ignoring: false, renderObject: RenderIgnorePointer#2b763) flutter: │ └RepaintBoundary-[GlobalKey#628f4](renderObject: RenderRepaintBoundary#5a53b) flutter: │ └Builder flutter: │ └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#f8795) flutter: │ └AppHome flutter: │ └Material(type: canvas, dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#61ca6]], state: _MaterialState#7d183) flutter: │ └AnimatedPhysicalModel(duration: 200ms, shape: rectangle, borderRadius: BorderRadius.zero, elevation: 0.0, color: Color(0xfffafafa), animateColor: false, shadowColor: Color(0xff000000), animateShadowColor: true, state: _AnimatedPhysicalModelState#d479e(ticker inactive)) flutter: │ └PhysicalModel(shape: rectangle, borderRadius: BorderRadius.zero, elevation: 0.0, color: Color(0xfffafafa), shadowColor: Color(0xff000000), renderObject: RenderPhysicalModel#c60b5) flutter: │ └NotificationListener flutter: │ └_InkFeatures-[GlobalKey#e9da0 ink renderer](renderObject: _RenderInkFeatures#d8e6d) flutter: │ └AnimatedDefaultTextStyle(duration: 200ms, debugLabel: (englishLike bodyMedium 2014).merge(blackRedwoodCity bodyMedium), inherit: false, color: Color(0xdd000000), family: .AppleSystemUIFont, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none, softWrap: wrapping at box width, overflow: clip, state: _AnimatedDefaultTextStyleState#12f43(ticker inactive)) flutter: │ └DefaultTextStyle(debugLabel: (englishLike bodyMedium 2014).merge(blackRedwoodCity bodyMedium), inherit: false, color: Color(0xdd000000), family: .AppleSystemUIFont, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none, softWrap: wrapping at box width, overflow: clip) flutter: │ └Center(alignment: Alignment.center, dependencies: [Directionality], renderObject: RenderPositionedBox#b088f) flutter: │ └TextButton(dirty, dependencies: [MediaQuery, _InheritedTheme, _LocalizationsScope-[GlobalKey#61ca6]], state: _ButtonStyleState#687c9) flutter: │ └Semantics(container: true, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#ca411 relayoutBoundary=up1) flutter: │ └_InputPadding(renderObject: _RenderInputPadding#60ede relayoutBoundary=up2) flutter: │ └ConstrainedBox(BoxConstraints(56.0<=w<=Infinity, 28.0<=h<=Infinity), renderObject: RenderConstrainedBox#34800 relayoutBoundary=up3) flutter: │ └Material(type: button, color: Color(0x00000000), shadowColor: Color(0xff000000), textStyle.debugLabel: ((englishLike labelLarge 2014).merge(blackRedwoodCity labelLarge)).copyWith, textStyle.inherit: false, textStyle.color: MaterialColor(primary value: Color(0xff2196f3)), textStyle.family: .AppleSystemUIFont, textStyle.size: 14.0, textStyle.weight: 500, textStyle.baseline: alphabetic, textStyle.decoration: TextDecoration.none, shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(4.0)), dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#61ca6]], state: _MaterialState#50a4d(tickers: tracking 5 tickers)) flutter: │ └_MaterialInterior(duration: 200ms, shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(4.0)), elevation: 0.0, color: Color(0x00000000), shadowColor: Color(0xff000000), dependencies: [Directionality, _InheritedTheme, _LocalizationsScope-[GlobalKey#61ca6]], state: _MaterialInteriorState#d296d(ticker inactive)) flutter: │ └PhysicalShape(clipper: ShapeBorderClipper, elevation: 0.0, color: Color(0x00000000), shadowColor: Color(0xff000000), renderObject: RenderPhysicalShape#43df6 relayoutBoundary=up4) flutter: │ └_ShapeBorderPaint(dependencies: [Directionality]) flutter: │ └CustomPaint(renderObject: RenderCustomPaint#c1a3c relayoutBoundary=up5) flutter: │ └NotificationListener flutter: │ └_InkFeatures-[GlobalKey#625bc ink renderer](renderObject: _RenderInkFeatures#54439 relayoutBoundary=up6) flutter: │ └AnimatedDefaultTextStyle(duration: 200ms, debugLabel: ((englishLike labelLarge 2014).merge(blackRedwoodCity labelLarge)).copyWith, inherit: false, color: MaterialColor(primary value: Color(0xff2196f3)), family: .AppleSystemUIFont, size: 14.0, weight: 500, baseline: alphabetic, decoration: TextDecoration.none, softWrap: wrapping at box width, overflow: clip, state: _AnimatedDefaultTextStyleState#2f29d(ticker inactive)) flutter: │ └DefaultTextStyle(debugLabel: ((englishLike labelLarge 2014).merge(blackRedwoodCity labelLarge)).copyWith, inherit: false, color: MaterialColor(primary value: Color(0xff2196f3)), family: .AppleSystemUIFont, size: 14.0, weight: 500, baseline: alphabetic, decoration: TextDecoration.none, softWrap: wrapping at box width, overflow: clip) flutter: │ └InkWell flutter: │ └_InkResponseStateWidget(gestures: [tap], mouseCursor: ButtonStyleButton_MouseCursor, clipped to BoxShape.rectangle, dirty, dependencies: [Directionality, MediaQuery, _InheritedTheme, _LocalizationsScope-[GlobalKey#61ca6]], state: _InkResponseState#0b11d) flutter: │ └_ParentInkResponseProvider flutter: │ └Actions(dispatcher: null, actions: {ActivateIntent: CallbackAction#018db, ButtonActivateIntent: CallbackAction#ef87a}, state: _ActionsState#a5eab) flutter: │ └_ActionsScope flutter: │ └Focus(dependencies: [_FocusInheritedScope], state: _FocusState#5a9de) flutter: │ └_FocusInheritedScope flutter: │ └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#8ac3e relayoutBoundary=up7) flutter: │ └MouseRegion(listeners: [enter, exit], cursor: SystemMouseCursor(click), renderObject: RenderMouseRegion#13d4e relayoutBoundary=up8) flutter: │ └Builder(dependencies: [DefaultSelectionStyle]) flutter: │ └DefaultSelectionStyle flutter: │ └Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#d99cc relayoutBoundary=up9) flutter: │ └GestureDetector(startBehavior: start, dependencies: [MediaQuery]) flutter: │ └RawGestureDetector(state: RawGestureDetectorState#b8d93(gestures: [tap], excludeFromSemantics: true, behavior: opaque)) flutter: │ └Listener(listeners: [down, panZoomStart], behavior: opaque, renderObject: RenderPointerListener#a4c3b relayoutBoundary=up10) flutter: │ └Builder(dependencies: [IconTheme]) flutter: │ └IconTheme(color: MaterialColor(primary value: Color(0xff2196f3))) flutter: │ └Padding(padding: EdgeInsets(8.0, 0.0, 8.0, 0.0), dependencies: [Directionality], renderObject: RenderPadding#18a87 relayoutBoundary=up11) flutter: │ └Align(alignment: Alignment.center, widthFactor: 1.0, heightFactor: 1.0, dependencies: [Directionality], renderObject: RenderPositionedBox#fb8a8 relayoutBoundary=up12) flutter: │ └Text("Dump Widget Tree", dependencies: [DefaultSelectionStyle, DefaultTextStyle, MediaQuery]) flutter: │ └RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "Dump Widget Tree", dependencies: [Directionality, _LocalizationsScope-[GlobalKey#61ca6]], renderObject: RenderParagraph#d15aa relayoutBoundary=up13) flutter: └PositionedDirectional(dependencies: [Directionality]) flutter: └Positioned(left: 0.0, top: 0.0, bottom: 0.0, width: 20.0) flutter: └Listener(listeners: [down], behavior: translucent, renderObject: RenderPointerListener#d884c) flutter: flutter: ```
When the button changes from being pressed to being released, this invokes the `debugDumpApp()` function. It also coincides with the [`TextButton`][] object calling [`setState()`][] and thus marking itself dirty. This explains why a Flutter marks a specific object as "dirty". When you review the widget tree, look for a line that resembles the following: ```plaintext └TextButton(dirty, dependencies: [MediaQuery, _InheritedTheme, _LocalizationsScope-[GlobalKey#5880d]], state: _ButtonStyleState#ab76e) ``` If you write your own widgets, override the [`debugFillProperties()`][widget-fill] method to add information. Add [DiagnosticsProperty][] objects to the method's argument and call the superclass method. The `toString` method uses this function to fill in the widget's description. ### Print the render tree When debugging a layout issue, the Widgets layer's tree might lack detail. The next level of debugging might require a render tree. To dump the render tree: 1. Open your source file. 1. Call the [`debugDumpRenderTree()`][] function. You can call this any time except during a layout or paint phase. Consider calling it from a [frame callback][] or an event handler. 1. If you haven't started your app, debug it using your IDE. 1. If you have started your app, save your source file. Hot reload re-renders your app. #### Example 5: Call `debugDumpRenderTree()` ```dart import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp(home: AppHome())); } class AppHome extends StatelessWidget { const AppHome({super.key}); @override Widget build(BuildContext context) { return Material( child: Center( child: TextButton( onPressed: () { debugDumpRenderTree(); }, child: const Text('Dump Render Tree'), ), ), ); } } ``` When debugging layout issues, look at the `size` and `constraints` fields. The constraints flow down the tree and the sizes flow back up.
Expand to view the render tree for Example 5 ```plaintext flutter: RenderView#02c80 flutter: │ debug mode enabled - macos flutter: │ view size: Size(800.0, 600.0) (in physical pixels) flutter: │ device pixel ratio: 1.0 (physical pixels per logical pixel) flutter: │ configuration: Size(800.0, 600.0) at 1.0x (in logical pixels) flutter: │ flutter: └─child: RenderSemanticsAnnotations#fe6b5 flutter: │ needs compositing flutter: │ creator: Semantics ← _FocusInheritedScope ← Focus ← flutter: │ HeroControllerScope ← ScrollConfiguration ← MaterialApp ← flutter: │ MediaQuery ← _MediaQueryFromView ← _ViewScope ← flutter: │ View-[GlobalObjectKey FlutterView#6cffa] ← [root] flutter: │ parentData: flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ flutter: └─child: RenderSemanticsAnnotations#6edef flutter: │ needs compositing flutter: │ creator: Semantics ← _FocusInheritedScope ← Focus ← Shortcuts ← flutter: │ _SharedAppModel ← SharedAppData ← UnmanagedRestorationScope ← flutter: │ RestorationScope ← UnmanagedRestorationScope ← flutter: │ RootRestorationScope ← WidgetsApp-[GlobalObjectKey flutter: │ _MaterialAppState#5c303] ← Semantics ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ flutter: └─child: RenderSemanticsAnnotations#e8ce8 flutter: │ needs compositing flutter: │ creator: Semantics ← _FocusInheritedScope ← Focus ← Shortcuts ← flutter: │ DefaultTextEditingShortcuts ← Semantics ← _FocusInheritedScope flutter: │ ← Focus ← Shortcuts ← _SharedAppModel ← SharedAppData ← flutter: │ UnmanagedRestorationScope ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ flutter: └─child: RenderSemanticsAnnotations#fc545 flutter: │ needs compositing flutter: │ creator: Semantics ← _FocusInheritedScope ← Focus ← Shortcuts ← flutter: │ Semantics ← _FocusInheritedScope ← Focus ← Shortcuts ← flutter: │ DefaultTextEditingShortcuts ← Semantics ← _FocusInheritedScope flutter: │ ← Focus ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ flutter: └─child: RenderTapRegionSurface#ff857 flutter: │ needs compositing flutter: │ creator: TapRegionSurface ← _FocusInheritedScope ← Focus ← flutter: │ FocusTraversalGroup ← _ActionsScope ← Actions ← Semantics ← flutter: │ _FocusInheritedScope ← Focus ← Shortcuts ← Semantics ← flutter: │ _FocusInheritedScope ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ behavior: deferToChild flutter: │ flutter: └─child: RenderSemanticsAnnotations#fe316 flutter: │ needs compositing flutter: │ creator: Semantics ← _FocusInheritedScope ← Focus ← Shortcuts ← flutter: │ _ShortcutRegistrarScope ← ShortcutRegistrar ← TapRegionSurface flutter: │ ← _FocusInheritedScope ← Focus ← FocusTraversalGroup ← flutter: │ _ActionsScope ← Actions ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ flutter: └─child: RenderSemanticsAnnotations#fa55c flutter: │ needs compositing flutter: │ creator: Semantics ← Localizations ← Semantics ← flutter: │ _FocusInheritedScope ← Focus ← Shortcuts ← flutter: │ _ShortcutRegistrarScope ← ShortcutRegistrar ← TapRegionSurface flutter: │ ← _FocusInheritedScope ← Focus ← FocusTraversalGroup ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ flutter: └─child: RenderCustomPaint#4b256 flutter: │ needs compositing flutter: │ creator: CustomPaint ← Banner ← CheckedModeBanner ← Title ← flutter: │ Directionality ← _LocalizationsScope-[GlobalKey#4a3aa] ← flutter: │ Semantics ← Localizations ← Semantics ← _FocusInheritedScope ← flutter: │ Focus ← Shortcuts ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ painter: null flutter: │ foregroundPainter: BannerPainter#1bfd7(Instance of flutter: │ '_SystemFontsNotifier') flutter: │ flutter: └─child: RenderSemanticsAnnotations#f470f flutter: │ needs compositing flutter: │ creator: Semantics ← FocusScope ← DefaultSelectionStyle ← flutter: │ IconTheme ← IconTheme ← _InheritedCupertinoTheme ← flutter: │ CupertinoTheme ← _InheritedTheme ← Theme ← AnimatedTheme ← flutter: │ DefaultSelectionStyle ← _ScaffoldMessengerScope ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ flutter: └─child: RenderPointerListener#f59c8 flutter: │ needs compositing flutter: │ creator: Listener ← HeroControllerScope ← flutter: │ Navigator-[GlobalObjectKey flutter: │ _WidgetsAppState#0d73a] ← _FocusInheritedScope ← Semantics ← flutter: │ FocusScope ← DefaultSelectionStyle ← IconTheme ← IconTheme ← flutter: │ _InheritedCupertinoTheme ← CupertinoTheme ← _InheritedTheme ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ behavior: deferToChild flutter: │ listeners: down, up, cancel flutter: │ flutter: └─child: RenderAbsorbPointer#c91bd flutter: │ needs compositing flutter: │ creator: AbsorbPointer ← Listener ← HeroControllerScope ← flutter: │ Navigator-[GlobalObjectKey flutter: │ _WidgetsAppState#0d73a] ← _FocusInheritedScope ← Semantics ← flutter: │ FocusScope ← DefaultSelectionStyle ← IconTheme ← IconTheme ← flutter: │ _InheritedCupertinoTheme ← CupertinoTheme ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ absorbing: false flutter: │ ignoringSemantics: null flutter: │ flutter: └─child: _RenderTheater#07897 flutter: │ needs compositing flutter: │ creator: _Theater ← flutter: │ Overlay-[LabeledGlobalKey#49a93] ← flutter: │ UnmanagedRestorationScope ← _FocusInheritedScope ← Focus ← flutter: │ _FocusInheritedScope ← Focus ← FocusTraversalGroup ← flutter: │ AbsorbPointer ← Listener ← HeroControllerScope ← flutter: │ Navigator-[GlobalObjectKey flutter: │ _WidgetsAppState#0d73a] ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ skipCount: 0 flutter: │ textDirection: ltr flutter: │ flutter: ├─onstage 1: RenderIgnorePointer#3b659 flutter: │ │ creator: IgnorePointer ← _RenderTheaterMarker ← flutter: │ │ _EffectiveTickerMode ← TickerMode ← flutter: │ │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#a47f4] flutter: │ │ ← _Theater ← Overlay-[LabeledGlobalKey#49a93] ← flutter: │ │ UnmanagedRestorationScope ← _FocusInheritedScope ← Focus ← flutter: │ │ _FocusInheritedScope ← Focus ← ⋯ flutter: │ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use flutter: │ │ size) flutter: │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ │ size: Size(800.0, 600.0) flutter: │ │ ignoring: false flutter: │ │ ignoringSemantics: null flutter: │ │ flutter: │ └─child: RenderBlockSemantics#7586c flutter: │ │ creator: BlockSemantics ← ModalBarrier ← IgnorePointer ← flutter: │ │ _RenderTheaterMarker ← _EffectiveTickerMode ← TickerMode ← flutter: │ │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#a47f4] flutter: │ │ ← _Theater ← Overlay-[LabeledGlobalKey#49a93] ← flutter: │ │ UnmanagedRestorationScope ← _FocusInheritedScope ← Focus ← ⋯ flutter: │ │ parentData: (can use size) flutter: │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ │ blocks semantics of earlier render objects below the common flutter: │ │ boundary flutter: │ │ size: Size(800.0, 600.0) flutter: │ │ blocking: true flutter: │ │ flutter: │ └─child: RenderExcludeSemantics#c1d3f flutter: │ │ creator: ExcludeSemantics ← BlockSemantics ← ModalBarrier ← flutter: │ │ IgnorePointer ← _RenderTheaterMarker ← _EffectiveTickerMode ← flutter: │ │ TickerMode ← flutter: │ │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#a47f4] flutter: │ │ ← _Theater ← Overlay-[LabeledGlobalKey#49a93] ← flutter: │ │ UnmanagedRestorationScope ← _FocusInheritedScope ← ⋯ flutter: │ │ parentData: (can use size) flutter: │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ │ size: Size(800.0, 600.0) flutter: │ │ excluding: true flutter: │ │ flutter: │ └─child: RenderSemanticsGestureHandler#70b16 flutter: │ │ creator: _GestureSemantics ← RawGestureDetector ← flutter: │ │ _ModalBarrierGestureDetector ← ExcludeSemantics ← flutter: │ │ BlockSemantics ← ModalBarrier ← IgnorePointer ← flutter: │ │ _RenderTheaterMarker ← _EffectiveTickerMode ← TickerMode ← flutter: │ │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#a47f4] flutter: │ │ ← _Theater ← ⋯ flutter: │ │ parentData: (can use size) flutter: │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ │ size: Size(800.0, 600.0) flutter: │ │ behavior: opaque flutter: │ │ gestures: flutter: │ │ flutter: │ └─child: RenderPointerListener#1f34a flutter: │ │ creator: Listener ← _GestureSemantics ← RawGestureDetector ← flutter: │ │ _ModalBarrierGestureDetector ← ExcludeSemantics ← flutter: │ │ BlockSemantics ← ModalBarrier ← IgnorePointer ← flutter: │ │ _RenderTheaterMarker ← _EffectiveTickerMode ← TickerMode ← flutter: │ │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#a47f4] flutter: │ │ ← ⋯ flutter: │ │ parentData: (can use size) flutter: │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ │ size: Size(800.0, 600.0) flutter: │ │ behavior: opaque flutter: │ │ listeners: down, panZoomStart flutter: │ │ flutter: │ └─child: RenderSemanticsAnnotations#73467 flutter: │ │ creator: Semantics ← Listener ← _GestureSemantics ← flutter: │ │ RawGestureDetector ← _ModalBarrierGestureDetector ← flutter: │ │ ExcludeSemantics ← BlockSemantics ← ModalBarrier ← flutter: │ │ IgnorePointer ← _RenderTheaterMarker ← _EffectiveTickerMode ← flutter: │ │ TickerMode ← ⋯ flutter: │ │ parentData: (can use size) flutter: │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ │ size: Size(800.0, 600.0) flutter: │ │ flutter: │ └─child: RenderMouseRegion#560dc flutter: │ │ creator: MouseRegion ← Semantics ← Listener ← _GestureSemantics ← flutter: │ │ RawGestureDetector ← _ModalBarrierGestureDetector ← flutter: │ │ ExcludeSemantics ← BlockSemantics ← ModalBarrier ← flutter: │ │ IgnorePointer ← _RenderTheaterMarker ← _EffectiveTickerMode ← ⋯ flutter: │ │ parentData: (can use size) flutter: │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ │ size: Size(800.0, 600.0) flutter: │ │ behavior: opaque flutter: │ │ listeners: flutter: │ │ cursor: SystemMouseCursor(basic) flutter: │ │ flutter: │ └─child: RenderConstrainedBox#01e8c flutter: │ creator: ConstrainedBox ← MouseRegion ← Semantics ← Listener ← flutter: │ _GestureSemantics ← RawGestureDetector ← flutter: │ _ModalBarrierGestureDetector ← ExcludeSemantics ← flutter: │ BlockSemantics ← ModalBarrier ← IgnorePointer ← flutter: │ _RenderTheaterMarker ← ⋯ flutter: │ parentData: (can use size) flutter: │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: │ size: Size(800.0, 600.0) flutter: │ additionalConstraints: BoxConstraints(biggest) flutter: │ flutter: ├─onstage 2: RenderSemanticsAnnotations#8187b flutter: ╎ │ needs compositing flutter: ╎ │ creator: Semantics ← _RenderTheaterMarker ← _EffectiveTickerMode flutter: ╎ │ ← TickerMode ← flutter: ╎ │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#8cd54] flutter: ╎ │ ← _Theater ← Overlay-[LabeledGlobalKey#49a93] ← flutter: ╎ │ UnmanagedRestorationScope ← _FocusInheritedScope ← Focus ← flutter: ╎ │ _FocusInheritedScope ← Focus ← ⋯ flutter: ╎ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use flutter: ╎ │ size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ flutter: ╎ └─child: RenderOffstage#f211d flutter: ╎ │ needs compositing flutter: ╎ │ creator: Offstage ← _ModalScopeStatus ← UnmanagedRestorationScope flutter: ╎ │ ← RestorationScope ← AnimatedBuilder ← flutter: ╎ │ _ModalScope-[LabeledGlobalKey<_ModalScopeState>#db401] flutter: ╎ │ ← Semantics ← _RenderTheaterMarker ← _EffectiveTickerMode ← flutter: ╎ │ TickerMode ← flutter: ╎ │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#8cd54] flutter: ╎ │ ← _Theater ← ⋯ flutter: ╎ │ parentData: (can use size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ offstage: false flutter: ╎ │ flutter: ╎ └─child: RenderSemanticsAnnotations#9436c flutter: ╎ │ needs compositing flutter: ╎ │ creator: Semantics ← FocusScope ← PrimaryScrollController ← flutter: ╎ │ _ActionsScope ← Actions ← Builder ← PageStorage ← Offstage ← flutter: ╎ │ _ModalScopeStatus ← UnmanagedRestorationScope ← flutter: ╎ │ RestorationScope ← AnimatedBuilder ← ⋯ flutter: ╎ │ parentData: (can use size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ flutter: ╎ └─child: RenderRepaintBoundary#f8f28 flutter: ╎ │ needs compositing flutter: ╎ │ creator: RepaintBoundary ← _FocusInheritedScope ← Semantics ← flutter: ╎ │ FocusScope ← PrimaryScrollController ← _ActionsScope ← Actions flutter: ╎ │ ← Builder ← PageStorage ← Offstage ← _ModalScopeStatus ← flutter: ╎ │ UnmanagedRestorationScope ← ⋯ flutter: ╎ │ parentData: (can use size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ layer: OffsetLayer#e73b7 flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ metrics: 66.7% useful (1 bad vs 2 good) flutter: ╎ │ diagnosis: insufficient data to draw conclusion (less than five flutter: ╎ │ repaints) flutter: ╎ │ flutter: ╎ └─child: RenderFractionalTranslation#c3a54 flutter: ╎ │ needs compositing flutter: ╎ │ creator: FractionalTranslation ← SlideTransition ← flutter: ╎ │ CupertinoPageTransition ← AnimatedBuilder ← RepaintBoundary ← flutter: ╎ │ _FocusInheritedScope ← Semantics ← FocusScope ← flutter: ╎ │ PrimaryScrollController ← _ActionsScope ← Actions ← Builder ← ⋯ flutter: ╎ │ parentData: (can use size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ translation: Offset(0.0, 0.0) flutter: ╎ │ transformHitTests: false flutter: ╎ │ flutter: ╎ └─child: RenderFractionalTranslation#7fcf2 flutter: ╎ │ needs compositing flutter: ╎ │ creator: FractionalTranslation ← SlideTransition ← flutter: ╎ │ FractionalTranslation ← SlideTransition ← flutter: ╎ │ CupertinoPageTransition ← AnimatedBuilder ← RepaintBoundary ← flutter: ╎ │ _FocusInheritedScope ← Semantics ← FocusScope ← flutter: ╎ │ PrimaryScrollController ← _ActionsScope ← ⋯ flutter: ╎ │ parentData: (can use size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ translation: Offset(0.0, 0.0) flutter: ╎ │ transformHitTests: true flutter: ╎ │ flutter: ╎ └─child: RenderDecoratedBox#713ec flutter: ╎ │ needs compositing flutter: ╎ │ creator: DecoratedBox ← DecoratedBoxTransition ← flutter: ╎ │ FractionalTranslation ← SlideTransition ← FractionalTranslation flutter: ╎ │ ← SlideTransition ← CupertinoPageTransition ← AnimatedBuilder ← flutter: ╎ │ RepaintBoundary ← _FocusInheritedScope ← Semantics ← FocusScope flutter: ╎ │ ← ⋯ flutter: ╎ │ parentData: (can use size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ ├─decoration: _CupertinoEdgeShadowDecoration flutter: ╎ │ colors: Color(0x04000000), Color(0x00000000) flutter: ╎ │ flutter: ╎ │ configuration: ImageConfiguration(bundle: flutter: ╎ │ PlatformAssetBundle#164ca(), devicePixelRatio: 1.0, locale: flutter: ╎ │ en_US, textDirection: TextDirection.ltr, platform: macOS) flutter: ╎ │ flutter: ╎ └─child: RenderStack#83b13 flutter: ╎ │ needs compositing flutter: ╎ │ creator: Stack ← _CupertinoBackGestureDetector ← flutter: ╎ │ DecoratedBox ← DecoratedBoxTransition ← FractionalTranslation ← flutter: ╎ │ SlideTransition ← FractionalTranslation ← SlideTransition ← flutter: ╎ │ CupertinoPageTransition ← AnimatedBuilder ← RepaintBoundary ← flutter: ╎ │ _FocusInheritedScope ← ⋯ flutter: ╎ │ parentData: (can use size) flutter: ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ size: Size(800.0, 600.0) flutter: ╎ │ alignment: AlignmentDirectional.topStart flutter: ╎ │ textDirection: ltr flutter: ╎ │ fit: passthrough flutter: ╎ │ flutter: ╎ ├─child 1: RenderIgnorePointer#ad50f flutter: ╎ │ │ needs compositing flutter: ╎ │ │ creator: IgnorePointer ← AnimatedBuilder ← Stack ← flutter: ╎ │ │ _CupertinoBackGestureDetector ← DecoratedBox ← flutter: ╎ │ │ DecoratedBoxTransition ← FractionalTranslation ← flutter: ╎ │ │ SlideTransition ← FractionalTranslation ← SlideTransition ← flutter: ╎ │ │ CupertinoPageTransition ← AnimatedBuilder ← ⋯ flutter: ╎ │ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use flutter: ╎ │ │ size) flutter: ╎ │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ │ size: Size(800.0, 600.0) flutter: ╎ │ │ ignoring: false flutter: ╎ │ │ ignoringSemantics: null flutter: ╎ │ │ flutter: ╎ │ └─child: RenderRepaintBoundary#29754 flutter: ╎ │ │ needs compositing flutter: ╎ │ │ creator: RepaintBoundary-[GlobalKey#75409] ← IgnorePointer ← flutter: ╎ │ │ AnimatedBuilder ← Stack ← flutter: ╎ │ │ _CupertinoBackGestureDetector ← DecoratedBox ← flutter: ╎ │ │ DecoratedBoxTransition ← FractionalTranslation ← flutter: ╎ │ │ SlideTransition ← FractionalTranslation ← SlideTransition ← flutter: ╎ │ │ CupertinoPageTransition ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ │ layer: OffsetLayer#fa835 flutter: ╎ │ │ size: Size(800.0, 600.0) flutter: ╎ │ │ metrics: 90.9% useful (1 bad vs 10 good) flutter: ╎ │ │ diagnosis: this is an outstandingly useful repaint boundary and flutter: ╎ │ │ should definitely be kept flutter: ╎ │ │ flutter: ╎ │ └─child: RenderSemanticsAnnotations#95566 flutter: ╎ │ │ creator: Semantics ← Builder ← RepaintBoundary-[GlobalKey#75409] flutter: ╎ │ │ ← IgnorePointer ← AnimatedBuilder ← Stack ← flutter: ╎ │ │ _CupertinoBackGestureDetector ← DecoratedBox ← flutter: ╎ │ │ DecoratedBoxTransition ← FractionalTranslation ← flutter: ╎ │ │ SlideTransition ← FractionalTranslation ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ │ size: Size(800.0, 600.0) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderPhysicalModel#bc9d7 flutter: ╎ │ │ creator: PhysicalModel ← AnimatedPhysicalModel ← Material ← flutter: ╎ │ │ AppHome ← Semantics ← Builder ← flutter: ╎ │ │ RepaintBoundary-[GlobalKey#75409] ← IgnorePointer ← flutter: ╎ │ │ AnimatedBuilder ← Stack ← flutter: ╎ │ │ _CupertinoBackGestureDetector ← DecoratedBox ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ │ size: Size(800.0, 600.0) flutter: ╎ │ │ elevation: 0.0 flutter: ╎ │ │ color: Color(0xfffafafa) flutter: ╎ │ │ shadowColor: Color(0xfffafafa) flutter: ╎ │ │ shape: BoxShape.rectangle flutter: ╎ │ │ borderRadius: BorderRadius.zero flutter: ╎ │ │ flutter: ╎ │ └─child: _RenderInkFeatures#ac819 flutter: ╎ │ │ creator: _InkFeatures-[GlobalKey#d721e ink renderer] ← flutter: ╎ │ │ NotificationListener ← PhysicalModel flutter: ╎ │ │ ← AnimatedPhysicalModel ← Material ← AppHome ← Semantics ← flutter: ╎ │ │ Builder ← RepaintBoundary-[GlobalKey#75409] ← IgnorePointer ← flutter: ╎ │ │ AnimatedBuilder ← Stack ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ │ size: Size(800.0, 600.0) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderPositionedBox#dc1df flutter: ╎ │ │ creator: Center ← DefaultTextStyle ← AnimatedDefaultTextStyle ← flutter: ╎ │ │ _InkFeatures-[GlobalKey#d721e ink renderer] ← flutter: ╎ │ │ NotificationListener ← PhysicalModel flutter: ╎ │ │ ← AnimatedPhysicalModel ← Material ← AppHome ← Semantics ← flutter: ╎ │ │ Builder ← RepaintBoundary-[GlobalKey#75409] ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(w=800.0, h=600.0) flutter: ╎ │ │ size: Size(800.0, 600.0) flutter: ╎ │ │ alignment: Alignment.center flutter: ╎ │ │ textDirection: ltr flutter: ╎ │ │ widthFactor: expand flutter: ╎ │ │ heightFactor: expand flutter: ╎ │ │ flutter: ╎ │ └─child: RenderSemanticsAnnotations#a0a4b relayoutBoundary=up1 flutter: ╎ │ │ creator: Semantics ← TextButton ← Center ← DefaultTextStyle ← flutter: ╎ │ │ AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#d721e ink flutter: ╎ │ │ renderer] ← NotificationListener ← flutter: ╎ │ │ PhysicalModel ← AnimatedPhysicalModel ← Material ← AppHome ← flutter: ╎ │ │ Semantics ← ⋯ flutter: ╎ │ │ parentData: offset=Offset(329.0, 286.0) (can use size) flutter: ╎ │ │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0) flutter: ╎ │ │ semantic boundary flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ flutter: ╎ │ └─child: _RenderInputPadding#4672f relayoutBoundary=up2 flutter: ╎ │ │ creator: _InputPadding ← Semantics ← TextButton ← Center ← flutter: ╎ │ │ DefaultTextStyle ← AnimatedDefaultTextStyle ← flutter: ╎ │ │ _InkFeatures-[GlobalKey#d721e ink renderer] ← flutter: ╎ │ │ NotificationListener ← PhysicalModel flutter: ╎ │ │ ← AnimatedPhysicalModel ← Material ← AppHome ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderConstrainedBox#425d6 relayoutBoundary=up3 flutter: ╎ │ │ creator: ConstrainedBox ← _InputPadding ← Semantics ← TextButton flutter: ╎ │ │ ← Center ← DefaultTextStyle ← AnimatedDefaultTextStyle ← flutter: ╎ │ │ _InkFeatures-[GlobalKey#d721e ink renderer] ← flutter: ╎ │ │ NotificationListener ← PhysicalModel flutter: ╎ │ │ ← AnimatedPhysicalModel ← Material ← ⋯ flutter: ╎ │ │ parentData: offset=Offset(0.0, 0.0) (can use size) flutter: ╎ │ │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ additionalConstraints: BoxConstraints(56.0<=w<=Infinity, flutter: ╎ │ │ 28.0<=h<=Infinity) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderPhysicalShape#8e171 relayoutBoundary=up4 flutter: ╎ │ │ creator: PhysicalShape ← _MaterialInterior ← Material ← flutter: ╎ │ │ ConstrainedBox ← _InputPadding ← Semantics ← TextButton ← flutter: ╎ │ │ Center ← DefaultTextStyle ← AnimatedDefaultTextStyle ← flutter: ╎ │ │ _InkFeatures-[GlobalKey#d721e ink renderer] ← flutter: ╎ │ │ NotificationListener ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ elevation: 0.0 flutter: ╎ │ │ color: Color(0x00000000) flutter: ╎ │ │ shadowColor: Color(0x00000000) flutter: ╎ │ │ clipper: ShapeBorderClipper flutter: ╎ │ │ flutter: ╎ │ └─child: RenderCustomPaint#eea46 relayoutBoundary=up5 flutter: ╎ │ │ creator: CustomPaint ← _ShapeBorderPaint ← PhysicalShape ← flutter: ╎ │ │ _MaterialInterior ← Material ← ConstrainedBox ← _InputPadding ← flutter: ╎ │ │ Semantics ← TextButton ← Center ← DefaultTextStyle ← flutter: ╎ │ │ AnimatedDefaultTextStyle ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ painter: null flutter: ╎ │ │ foregroundPainter: _ShapeBorderPainter#ac724() flutter: ╎ │ │ flutter: ╎ │ └─child: _RenderInkFeatures#b19a7 relayoutBoundary=up6 flutter: ╎ │ │ creator: _InkFeatures-[GlobalKey#87971 ink renderer] ← flutter: ╎ │ │ NotificationListener ← CustomPaint ← flutter: ╎ │ │ _ShapeBorderPaint ← PhysicalShape ← _MaterialInterior ← flutter: ╎ │ │ Material ← ConstrainedBox ← _InputPadding ← Semantics ← flutter: ╎ │ │ TextButton ← Center ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderSemanticsAnnotations#4d1b3 relayoutBoundary=up7 flutter: ╎ │ │ creator: Semantics ← _FocusInheritedScope ← Focus ← _ActionsScope flutter: ╎ │ │ ← Actions ← _ParentInkResponseProvider ← flutter: ╎ │ │ _InkResponseStateWidget ← InkWell ← DefaultTextStyle ← flutter: ╎ │ │ AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#87971 ink flutter: ╎ │ │ renderer] ← NotificationListener ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderMouseRegion#e5b3f relayoutBoundary=up8 flutter: ╎ │ │ creator: MouseRegion ← Semantics ← _FocusInheritedScope ← Focus ← flutter: ╎ │ │ _ActionsScope ← Actions ← _ParentInkResponseProvider ← flutter: ╎ │ │ _InkResponseStateWidget ← InkWell ← DefaultTextStyle ← flutter: ╎ │ │ AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#87971 ink flutter: ╎ │ │ renderer] ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ behavior: opaque flutter: ╎ │ │ listeners: enter, exit flutter: ╎ │ │ cursor: SystemMouseCursor(click) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderSemanticsAnnotations#deb9b relayoutBoundary=up9 flutter: ╎ │ │ creator: Semantics ← DefaultSelectionStyle ← Builder ← flutter: ╎ │ │ MouseRegion ← Semantics ← _FocusInheritedScope ← Focus ← flutter: ╎ │ │ _ActionsScope ← Actions ← _ParentInkResponseProvider ← flutter: ╎ │ │ _InkResponseStateWidget ← InkWell ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ flutter: ╎ │ └─child: RenderPointerListener#2017a relayoutBoundary=up10 flutter: ╎ │ │ creator: Listener ← RawGestureDetector ← GestureDetector ← flutter: ╎ │ │ Semantics ← DefaultSelectionStyle ← Builder ← MouseRegion ← flutter: ╎ │ │ Semantics ← _FocusInheritedScope ← Focus ← _ActionsScope ← flutter: ╎ │ │ Actions ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ behavior: opaque flutter: ╎ │ │ listeners: down, panZoomStart flutter: ╎ │ │ flutter: ╎ │ └─child: RenderPadding#8455f relayoutBoundary=up11 flutter: ╎ │ │ creator: Padding ← IconTheme ← Builder ← Listener ← flutter: ╎ │ │ RawGestureDetector ← GestureDetector ← Semantics ← flutter: ╎ │ │ DefaultSelectionStyle ← Builder ← MouseRegion ← Semantics ← flutter: ╎ │ │ _FocusInheritedScope ← ⋯ flutter: ╎ │ │ parentData: (can use size) flutter: ╎ │ │ constraints: BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(142.0, 28.0) flutter: ╎ │ │ padding: EdgeInsets(8.0, 0.0, 8.0, 0.0) flutter: ╎ │ │ textDirection: ltr flutter: ╎ │ │ flutter: ╎ │ └─child: RenderPositionedBox#80b8d relayoutBoundary=up12 flutter: ╎ │ │ creator: Align ← Padding ← IconTheme ← Builder ← Listener ← flutter: ╎ │ │ RawGestureDetector ← GestureDetector ← Semantics ← flutter: ╎ │ │ DefaultSelectionStyle ← Builder ← MouseRegion ← Semantics ← ⋯ flutter: ╎ │ │ parentData: offset=Offset(8.0, 0.0) (can use size) flutter: ╎ │ │ constraints: BoxConstraints(40.0<=w<=784.0, 28.0<=h<=600.0) flutter: ╎ │ │ size: Size(126.0, 28.0) flutter: ╎ │ │ alignment: Alignment.center flutter: ╎ │ │ textDirection: ltr flutter: ╎ │ │ widthFactor: 1.0 flutter: ╎ │ │ heightFactor: 1.0 flutter: ╎ │ │ flutter: ╎ │ └─child: RenderParagraph#59bc2 relayoutBoundary=up13 flutter: ╎ │ │ creator: RichText ← Text ← Align ← Padding ← IconTheme ← Builder flutter: ╎ │ │ ← Listener ← RawGestureDetector ← GestureDetector ← Semantics ← flutter: ╎ │ │ DefaultSelectionStyle ← Builder ← ⋯ flutter: ╎ │ │ parentData: offset=Offset(0.0, 6.0) (can use size) flutter: ╎ │ │ constraints: BoxConstraints(0.0<=w<=784.0, 0.0<=h<=600.0) flutter: ╎ │ │ size: Size(126.0, 16.0) flutter: ╎ │ │ textAlign: start flutter: ╎ │ │ textDirection: ltr flutter: ╎ │ │ softWrap: wrapping at box width flutter: ╎ │ │ overflow: clip flutter: ╎ │ │ locale: en_US flutter: ╎ │ │ maxLines: unlimited flutter: ╎ │ ╘═╦══ text ═══ flutter: ╎ │ ║ TextSpan: flutter: ╎ │ ║ debugLabel: ((englishLike labelLarge 2014).merge(blackRedwoodCity flutter: ╎ │ ║ labelLarge)).copyWith flutter: ╎ │ ║ inherit: false flutter: ╎ │ ║ color: MaterialColor(primary value: Color(0xff2196f3)) flutter: ╎ │ ║ family: .AppleSystemUIFont flutter: ╎ │ ║ size: 14.0 flutter: ╎ │ ║ weight: 500 flutter: ╎ │ ║ baseline: alphabetic flutter: ╎ │ ║ decoration: TextDecoration.none flutter: ╎ │ ║ "Dump Render Tree" flutter: ╎ │ ╚═══════════ flutter: ╎ └─child 2: RenderPointerListener#db4b5 flutter: ╎ creator: Listener ← Positioned ← PositionedDirectional ← Stack ← flutter: ╎ _CupertinoBackGestureDetector ← DecoratedBox ← flutter: ╎ DecoratedBoxTransition ← FractionalTranslation ← flutter: ╎ SlideTransition ← FractionalTranslation ← SlideTransition ← flutter: ╎ CupertinoPageTransition ← ⋯ flutter: ╎ parentData: top=0.0; bottom=0.0; left=0.0; width=20.0; flutter: ╎ offset=Offset(0.0, 0.0) (can use size) flutter: ╎ constraints: BoxConstraints(w=20.0, h=600.0) flutter: ╎ size: Size(20.0, 600.0) flutter: ╎ behavior: translucent flutter: ╎ listeners: down flutter: ╎ flutter: └╌no offstage children flutter: ```
In the render tree for **Example 5**: * The `RenderView`, or window size, limits all render objects up to and including [`RenderPositionedBox`][]`#dc1df` render object to the size of the screen. This example sets the size to `Size(800.0, 600.0)` * The `constraints` property of each render object limits the size of each child. This property takes the [`BoxConstraints`][] render object as a value. Starting with the `RenderSemanticsAnnotations#fe6b5`, the constraint equals `BoxConstraints(w=800.0, h=600.0)`. * The [`Center`][] widget created the `RenderPositionedBox#dc1df` render object under the `RenderSemanticsAnnotations#8187b` subtree. * Each child under this render object has `BoxConstraints` with both minimum and maximum values. For example, `RenderSemanticsAnnotations#a0a4b` uses `BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)`. * All children of the `RenderPhysicalShape#8e171` render object use `BoxConstraints(BoxConstraints(56.0<=w<=800.0, 28.0<=h<=600.0))`. * The child `RenderPadding#8455f` sets a `padding` value of `EdgeInsets(8.0, 0.0, 8.0, 0.0)`. This sets a left and right padding of 8 to all subsequent children of this render object. They now have new constraints: `BoxConstraints(40.0<=w<=784.0, 28.0<=h<=600.0)`. This object, which the `creator` field tells us is probably part of the [`TextButton`][]'s definition, sets a minimum width of 88 pixels on its contents and a specific height of 36.0. This is the `TextButton` class implementing the Material Design guidelines regarding button dimensions. `RenderPositionedBox#80b8d` render object loosens the constraints again to center the text within the button. The [`RenderParagraph`][]#59bc2 render object picks its size based on its contents. If you follow the sizes back up the tree, you see how the size of the text influences the width of all the boxes that form the button. All parents take their child's dimensions to size themselves. Another way to notice this is by looking at the `relayoutBoundary` attribute of in the descriptions of each box. This tells you how many ancestors depend on this element's size. For example, the innermost `RenderPositionedBox` line has a `relayoutBoundary=up13`. This means that when Flutter marks the `RenderConstrainedBox` as dirty, it also marks box's 13 ancestors as dirty because the new dimensions might affect those ancestors. To add information to the dump if you write your own render objects, override [`debugFillProperties()`][render-fill]. Add [DiagnosticsProperty][] objects to the method's argument then call the superclass method. ### Print the layer tree To debug a compositing issue, use [`debugDumpLayerTree()`][]. #### Example 6: Call `debugDumpLayerTree()` ```dart import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp(home: AppHome())); } class AppHome extends StatelessWidget { const AppHome({super.key}); @override Widget build(BuildContext context) { return Material( child: Center( child: TextButton( onPressed: () { debugDumpLayerTree(); }, child: const Text('Dump Layer Tree'), ), ), ); } } ```
Expand to view the output of layer tree for Example 6 ```plaintext flutter: TransformLayer#214da flutter: │ owner: RenderView#ebaaf flutter: │ creator: [root] flutter: │ engine layer: TransformEngineLayer#535de flutter: │ handles: 1 flutter: │ offset: Offset(0.0, 0.0) flutter: │ transform: flutter: │ [0] 1.0,0.0,0.0,0.0 flutter: │ [1] 0.0,1.0,0.0,0.0 flutter: │ [2] 0.0,0.0,1.0,0.0 flutter: │ [3] 0.0,0.0,0.0,1.0 flutter: │ flutter: ├─child 1: OffsetLayer#0f766 flutter: │ │ creator: RepaintBoundary ← _FocusInheritedScope ← Semantics ← flutter: │ │ FocusScope ← PrimaryScrollController ← _ActionsScope ← Actions flutter: │ │ ← Builder ← PageStorage ← Offstage ← _ModalScopeStatus ← flutter: │ │ UnmanagedRestorationScope ← ⋯ flutter: │ │ engine layer: OffsetEngineLayer#1768d flutter: │ │ handles: 2 flutter: │ │ offset: Offset(0.0, 0.0) flutter: │ │ flutter: │ ├─child 1: PictureLayer#dd023 flutter: │ │ handles: 1 flutter: │ │ paint bounds: Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) flutter: │ │ picture: _NativePicture#36f94 flutter: │ │ raster cache hints: isComplex = false, willChange = false flutter: │ │ flutter: │ └─child 2: OffsetLayer#4cfc8 flutter: │ │ creator: RepaintBoundary-[GlobalKey#bd5d9] ← IgnorePointer ← flutter: │ │ AnimatedBuilder ← Stack ← flutter: │ │ _CupertinoBackGestureDetector ← DecoratedBox ← flutter: │ │ DecoratedBoxTransition ← FractionalTranslation ← flutter: │ │ SlideTransition ← FractionalTranslation ← SlideTransition ← flutter: │ │ CupertinoPageTransition ← ⋯ flutter: │ │ engine layer: OffsetEngineLayer#a1676 flutter: │ │ handles: 2 flutter: │ │ offset: Offset(0.0, 0.0) flutter: │ │ flutter: │ └─child 1: PictureLayer#aee55 flutter: │ handles: 1 flutter: │ paint bounds: Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) flutter: │ picture: _NativePicture#e732d flutter: │ raster cache hints: isComplex = false, willChange = false flutter: │ flutter: └─child 2: PictureLayer#b16e5 flutter: handles: 1 flutter: paint bounds: Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) flutter: picture: _NativePicture#eef0a flutter: raster cache hints: isComplex = false, willChange = false flutter: ```
The `RepaintBoundary` widget creates: 1. A `RenderRepaintBoundary` RenderObject in the render tree as shown in the **Example 5** results. ```plaintext ╎ └─child: RenderRepaintBoundary#f8f28 ╎ │ needs compositing ╎ │ creator: RepaintBoundary ← _FocusInheritedScope ← Semantics ← ╎ │ FocusScope ← PrimaryScrollController ← _ActionsScope ← Actions ╎ │ ← Builder ← PageStorage ← Offstage ← _ModalScopeStatus ← ╎ │ UnmanagedRestorationScope ← ⋯ ╎ │ parentData: (can use size) ╎ │ constraints: BoxConstraints(w=800.0, h=600.0) ╎ │ layer: OffsetLayer#e73b7 ╎ │ size: Size(800.0, 600.0) ╎ │ metrics: 66.7% useful (1 bad vs 2 good) ╎ │ diagnosis: insufficient data to draw conclusion (less than five ╎ │ repaints) ``` 1. A new layer in the layer tree as shown in the **Example 6** results. ```plaintext ├─child 1: OffsetLayer#0f766 │ │ creator: RepaintBoundary ← _FocusInheritedScope ← Semantics ← │ │ FocusScope ← PrimaryScrollController ← _ActionsScope ← Actions │ │ ← Builder ← PageStorage ← Offstage ← _ModalScopeStatus ← │ │ UnmanagedRestorationScope ← ⋯ │ │ engine layer: OffsetEngineLayer#1768d │ │ handles: 2 │ │ offset: Offset(0.0, 0.0) ``` This reduces how much needs to be repainted. ### Print the focus tree To debug a focus or shortcut issue, dump the focus tree using the [`debugDumpFocusTree()`][] function. The `debugDumpFocusTree()` method returns the focus tree for the app. The focus tree labels nodes in the following way: * The focused node is labeled `PRIMARY FOCUS`. * Ancestors of the focus nodes are labeled `IN FOCUS PATH`. If your app uses the [`Focus`][] widget, use the [`debugLabel`][] property to simplify finding its focus node in the tree. You can also use the [`debugFocusChanges`][] boolean property to enable extensive logging when the focus changes. #### Example 7: Call `debugDumpFocusTree()` ```dart import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp(home: AppHome())); } class AppHome extends StatelessWidget { const AppHome({super.key}); @override Widget build(BuildContext context) { return Material( child: Center( child: TextButton( onPressed: () { debugDumpFocusTree(); }, child: const Text('Dump Focus Tree'), ), ), ); } } ```
Expand to view the focus tree for Example 7 ```plaintext flutter: FocusManager#9d096 flutter: │ primaryFocus: FocusScopeNode#926dc(_ModalScopeState flutter: │ Focus Scope [PRIMARY FOCUS]) flutter: │ primaryFocusCreator: FocusScope ← PrimaryScrollController ← flutter: │ _ActionsScope ← Actions ← Builder ← PageStorage ← Offstage ← flutter: │ _ModalScopeStatus ← UnmanagedRestorationScope ← flutter: │ RestorationScope ← AnimatedBuilder ← flutter: │ _ModalScope-[LabeledGlobalKey<_ModalScopeState>#bd53e] flutter: │ ← Semantics ← _RenderTheaterMarker ← _EffectiveTickerMode ← flutter: │ TickerMode ← flutter: │ _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#89dd7] flutter: │ ← _Theater ← Overlay-[LabeledGlobalKey#52f82] ← flutter: │ UnmanagedRestorationScope ← ⋯ flutter: │ flutter: └─rootScope: FocusScopeNode#f4205(Root Focus Scope [IN FOCUS PATH]) flutter: │ IN FOCUS PATH flutter: │ focusedChildren: FocusScopeNode#a0d10(Navigator Scope [IN FOCUS flutter: │ PATH]) flutter: │ flutter: └─Child 1: FocusNode#088ec([IN FOCUS PATH]) flutter: │ context: Focus flutter: │ NOT FOCUSABLE flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: FocusNode#85f70(Shortcuts [IN FOCUS PATH]) flutter: │ context: Focus flutter: │ NOT FOCUSABLE flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: FocusNode#f0c18(Shortcuts [IN FOCUS PATH]) flutter: │ context: Focus flutter: │ NOT FOCUSABLE flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: FocusNode#0749f(Shortcuts [IN FOCUS PATH]) flutter: │ context: Focus flutter: │ NOT FOCUSABLE flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: _FocusTraversalGroupNode#28990(FocusTraversalGroup [IN FOCUS PATH]) flutter: │ context: Focus flutter: │ NOT FOCUSABLE flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: FocusNode#5b515(Shortcuts [IN FOCUS PATH]) flutter: │ context: Focus flutter: │ NOT FOCUSABLE flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: FocusScopeNode#a0d10(Navigator Scope [IN FOCUS PATH]) flutter: │ context: FocusScope flutter: │ IN FOCUS PATH flutter: │ focusedChildren: FocusScopeNode#926dc(_ModalScopeState flutter: │ Focus Scope [PRIMARY FOCUS]) flutter: │ flutter: └─Child 1: _FocusTraversalGroupNode#72c8a(FocusTraversalGroup [IN FOCUS PATH]) flutter: │ context: Focus flutter: │ NOT FOCUSABLE flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: FocusNode#eb709(Navigator [IN FOCUS PATH]) flutter: │ context: Focus flutter: │ IN FOCUS PATH flutter: │ flutter: └─Child 1: FocusScopeNode#926dc(_ModalScopeState Focus Scope [PRIMARY FOCUS]) flutter: │ context: FocusScope flutter: │ PRIMARY FOCUS flutter: │ flutter: └─Child 1: FocusNode#a6b74 flutter: context: Focus flutter: ```
### Print the semantics tree The `debugDumpSemanticsTree()` function prints the semantic tree for the app. The Semantics tree is presented to the system accessibility APIs. To obtain a dump of the Semantics tree: 1. Enable accessibility using a system accessibility tool or the `SemanticsDebugger` 1. Use the [`debugDumpSemanticsTree()`][] function. #### Example 8: Call `debugDumpSemanticsTree()` ```dart import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; void main() { runApp(const MaterialApp(home: AppHome())); } class AppHome extends StatelessWidget { const AppHome({super.key}); @override Widget build(BuildContext context) { return Material( child: Center( child: Semantics( button: true, enabled: true, label: 'Clickable text here!', child: GestureDetector( onTap: () { debugDumpSemanticsTree(); if (kDebugMode) { print('Clicked!'); } }, child: const Text('Click Me!', style: TextStyle(fontSize: 56)), ), ), ), ); } } ```
Expand to view the semantic tree for Example 8 ```plaintext flutter: SemanticsNode#0 flutter: │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) flutter: │ flutter: └─SemanticsNode#1 flutter: │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) flutter: │ textDirection: ltr flutter: │ flutter: └─SemanticsNode#2 flutter: │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) flutter: │ sortKey: OrdinalSortKey#824a2(order: 0.0) flutter: │ flutter: └─SemanticsNode#3 flutter: │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) flutter: │ flags: scopesRoute flutter: │ flutter: └─SemanticsNode#4 flutter: Rect.fromLTRB(278.0, 267.0, 522.0, 333.0) flutter: actions: tap flutter: flags: isButton, hasEnabledState, isEnabled flutter: label: flutter: "Clickable text here! flutter: Click Me!" flutter: textDirection: ltr flutter: flutter: Clicked! ```
### Print event timings If you want to find out where your events happen relative to the frame's begin and end, you can set prints to log these events. To print the beginning and end of the frames to the console, toggle the [`debugPrintBeginFrameBanner`][] and the [`debugPrintEndFrameBanner`][]. **The print frame banner log for Example 1** ```plaintext 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 : ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ``` To print the call stack causing the current frame to be scheduled, use the [`debugPrintScheduleFrameStacks`][] flag. ## Debug layout issues To debug a layout problem using a GUI, set [`debugPaintSizeEnabled`][] to `true`. This flag can be found in the `rendering` library. You can enable it at any time and affects all painting while `true`. Consider adding it to the top of your `void main()` entry point. #### Example 9 See an example in the following code: ```dart // Add import to the Flutter rendering library. import 'package:flutter/rendering.dart'; void main() { debugPaintSizeEnabled = true; runApp(const MyApp()); } ``` When enabled, Flutter displays the following changes to your app: * Displays all boxes in a bright teal border. * Displays all padding as a box with a faded blue fill and blue border around the child widget. * Displays all alignment positioning with yellow arrows. * Displays all spacers in gray, when they have no child. The [`debugPaintBaselinesEnabled`][] flag does something similar but for objects with baselines. The app displays the baseline for alphabetic characters in bright green and the baseline for ideographic characters in orange. Alphabetic characters "sit" on the alphabetic baseline, but that baseline "cuts" through the bottom of [CJK characters][cjk]. Flutter positions the ideographic baseline at the very bottom of the text line. The [`debugPaintPointersEnabled`][] flag turns on a special mode that highlights any objects that you tap in teal. This can help you determine if an object fails to hit test. This might happen if the object falls outside the bounds of its parent and thus not considered for hit testing in the first place. If you're trying to debug compositor layers, consider using the following flags. * Use the [`debugPaintLayerBordersEnabled`][] flag to find the boundaries of each layer. This flag results in outlining each layer's bounds in orange. * Use the [`debugRepaintRainbowEnabled`][] flag to display a repainted layer. Whenever a layer repaints, it overlays with a rotating set of colors. Any function or method in the Flutter framework that starts with `debug...` only works in [debug mode][]. [cjk]: https://en.wikipedia.org/wiki/CJK_characters ## Debug animation issues :::note To debug animations with the least effort, slow them down. To slow down the animation, click **Slow Animations** in DevTools' [Inspector view][]. This reduces the animation to 20% speed. If you want more control over the amount of slowness, use the following instructions. ::: Set the [`timeDilation`][] variable (from the `scheduler` library) to a number greater than 1.0, for instance, 50.0. It's best to only set this once on app startup. If you change it on the fly, especially if you reduce it while animations are running, it's possible that the framework will observe time going backwards, which will probably result in asserts and generally interfere with your efforts. ## Debug performance issues :::note You can achieve similar results to some of these debug flags using [DevTools][]. Some of the debug flags provide little benefit. If you find a flag with functionality you would like to add to [DevTools][], [file an issue][]. ::: Flutter provides a wide variety of top-level properties and functions to help you debug your app at various points along the development cycle. To use these features, compile your app in debug mode. The following list highlights some flags and one function from the [rendering library][] for debugging performance issues. [`debugDumpRenderTree()`][] : To dump the rendering tree to the console, call this function when not in a layout or repaint phase. To set these flags either: * Edit the framework code. * Import the module, set the value in your `main()` function, then hot restart. [`debugPaintLayerBordersEnabled`][] : To display the boundaries of each layer, set this property to `true`. When set, each layer paints a box around its boundary. [`debugRepaintRainbowEnabled`][] : To display a colored border around each widget, set this property to `true`. These borders change color as the app user scrolls in the app. To set this flag, add `debugRepaintRainbowEnabled = true;` as a top-level property in your app. If any static widgets rotate through colors after setting this flag, consider adding repaint boundaries to those areas. [`debugPrintMarkNeedsLayoutStacks`][] : To determine if your app creates more layouts than expected, set this property to `true`. This layout issue could happen on the timeline, on a profile, or from a `print` statement inside a layout method. When set, the framework outputs stack traces to the console to explain why your app marks each render object to be laid out. [`debugPrintMarkNeedsPaintStacks`][] : To determine if your app paints more layouts than expected, set this property to `true`. You can generate stack traces on demand as well. To print your own stack traces, add the `debugPrintStack()` function to your app. ### Trace Dart code performance :::note You can use the DevTools [Timeline events tab][] 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 and measure wall or CPU time of arbitrary segments of Dart code, use `dart:developer` [Timeline][] utilities. 1. Open your source code. 1. Wrap the code you want to measure in `Timeline` methods. ```dart import 'dart:developer'; void main() { Timeline.startSync('interesting function'); // iWonderHowLongThisTakes(); Timeline.finishSync(); } ``` 1. While connected to your app, open DevTools' [Timeline events tab][]. 1. Select the **Dart** recording option in the **Performance settings**. 1. Perform the function you want to measure. To ensure that the runtime performance characteristics closely match that of your final product, run your app in [profile mode][]. ### Add performance overlay :::note 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. ::: To enable the `PerformanceOverlay` widget in your code, set the `showPerformanceOverlay` property to `true` on the [`MaterialApp`][], [`CupertinoApp`][], or [`WidgetsApp`][] constructor: #### Example 10 ```dart import 'package:flutter/material.dart'; class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( showPerformanceOverlay: true, title: 'My Awesome App', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), ), home: const MyHomePage(title: 'My Awesome App'), ); } } ``` (If you're not using `MaterialApp`, `CupertinoApp`, or `WidgetsApp`, you can get the same effect by wrapping your application in a stack and putting a widget on your stack that was created by calling [`PerformanceOverlay.allEnabled()`][].) To learn how to interpret the graphs in the overlay, check out [The performance overlay][] in [Profiling Flutter performance][]. ## Add widget alignment grid To add an overlay to a [Material Design baseline grid][] on your app to help verify alignments, add the `debugShowMaterialGrid` argument in the [`MaterialApp` constructor][]. To add an overlay to non-Material applications, add a [`GridPaper`][] widget. [`_InkFeatures`]: https://api.flutter.dev/flutter/material/InkFeature-class.html [`BoxConstraints`]: https://api.flutter.dev/flutter/rendering/BoxConstraints-class.html [`Center`]: https://api.flutter.dev/flutter/widgets/Center-class.html [`CupertinoApp`]: https://api.flutter.dev/flutter/cupertino/CupertinoApp-class.html [`debugDumpApp()`]: https://api.flutter.dev/flutter/widgets/debugDumpApp.html [`debugDumpFocusTree()`]: https://api.flutter.dev/flutter/widgets/debugDumpFocusTree.html [`debugDumpLayerTree()`]: https://api.flutter.dev/flutter/rendering/debugDumpLayerTree.html [`debugDumpRenderTree()`]: https://api.flutter.dev/flutter/rendering/debugDumpRenderTree.html [`debugDumpSemanticsTree()`]: https://api.flutter.dev/flutter/rendering/debugDumpSemanticsTree.html [`debugFocusChanges`]: https://api.flutter.dev/flutter/widgets/debugFocusChanges.html [`debugLabel`]: https://api.flutter.dev/flutter/widgets/Focus/debugLabel.html [`debugPaintBaselinesEnabled`]: https://api.flutter.dev/flutter/rendering/debugPaintBaselinesEnabled.html [`debugPaintLayerBordersEnabled`]: https://api.flutter.dev/flutter/rendering/debugPaintLayerBordersEnabled.html [`debugPaintPointersEnabled`]: https://api.flutter.dev/flutter/rendering/debugPaintPointersEnabled.html [`debugPaintSizeEnabled`]: https://api.flutter.dev/flutter/rendering/debugPaintSizeEnabled.html [`debugPrint()`]: https://api.flutter.dev/flutter/widgets/debugPrint.html [`debugPrintBeginFrameBanner`]: https://api.flutter.dev/flutter/scheduler/debugPrintBeginFrameBanner.html [`debugPrintEndFrameBanner`]: https://api.flutter.dev/flutter/scheduler/debugPrintEndFrameBanner.html [`debugPrintMarkNeedsLayoutStacks`]: https://api.flutter.dev/flutter/rendering/debugPrintMarkNeedsLayoutStacks.html [`debugPrintMarkNeedsPaintStacks`]: https://api.flutter.dev/flutter/rendering/debugPrintMarkNeedsPaintStacks.html [`debugPrintScheduleFrameStacks`]: https://api.flutter.dev/flutter/scheduler/debugPrintScheduleFrameStacks.html [`debugRepaintRainbowEnabled`]: https://api.flutter.dev/flutter/rendering/debugRepaintRainbowEnabled.html [`Focus`]: https://api.flutter.dev/flutter/widgets/Focus-class.html [`GridPaper`]: https://api.flutter.dev/flutter/widgets/GridPaper-class.html [`log()`]: https://api.flutter.dev/flutter/dart-developer/log.html [`Material`]: https://api.flutter.dev/flutter/material/Material-class.html [`MaterialApp` constructor]: https://api.flutter.dev/flutter/material/MaterialApp/MaterialApp.html [`MaterialApp`]: https://api.flutter.dev/flutter/material/MaterialApp/MaterialApp.html [`PerformanceOverlay.allEnabled()`]: https://api.flutter.dev/flutter/widgets/PerformanceOverlay/PerformanceOverlay.allEnabled.html [`print()`]: https://api.flutter.dev/flutter/dart-core/print.html [`RenderParagraph`]: https://api.flutter.dev/flutter/rendering/RenderParagraph-class.html [`RenderPositionedBox`]: https://api.flutter.dev/flutter/rendering/RenderPositionedBox-class.html [`setState()`]: https://api.flutter.dev/flutter/widgets/State/setState.html [`stderr.method_to_invoke()`]: https://api.flutter.dev/flutter/dart-io/stderr.html [`TextButton`]: https://api.flutter.dev/flutter/material/TextButton-class.html [`timeDilation`]: https://api.flutter.dev/flutter/scheduler/timeDilation.html [`WidgetsApp`]: https://api.flutter.dev/flutter/widgets/WidgetsApp-class.html [debug mode]: /testing/build-modes#debug [Debugger]: /tools/devtools/debugger [Debugging]: /testing/debugging [DevTools]: /tools/devtools [DiagnosticsProperty]: https://api.flutter.dev/flutter/foundation/DiagnosticsProperty-class.html [file an issue]: https://github.com/flutter/devtools/issues [Flutter inspector]: /tools/devtools/inspector [frame callback]: https://api.flutter.dev/flutter/scheduler/SchedulerBinding/addPersistentFrameCallback.html [Inspector view]: /tools/devtools/inspector [Logging view]: /tools/devtools/logging [Material Design baseline grid]: https://m3.material.io/foundations/layout/understanding-layout/spacing [profile mode]: /testing/build-modes#profile [Profiling Flutter performance]: /perf/ui-performance [render-fill]: https://api.flutter.dev/flutter/rendering/Layer/debugFillProperties.html [rendering library]: https://api.flutter.dev/flutter/rendering/rendering-library.html [The performance overlay]: /perf/ui-performance#the-performance-overlay [Timeline events tab]: /tools/devtools/performance#timeline-events-tab [Timeline]: https://api.dart.dev/dart-developer/Timeline-class.html [widget-fill]: https://api.flutter.dev/flutter/widgets/Widget/debugFillProperties.html