Debugging Flutter apps programmatically
This doc describes debugging features that you can enable in code. For a full list of debugging and profiling tools, see the Debugging page.
Logging
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 on
stderr
and stdout
. For example:
stderr.writeln('print me');
If you output too much at once, then Android sometimes
discards some log lines. To avoid this, use debugPrint()
,
from Flutterβs foundation
library. This is a wrapper around print
that throttles the output to a level that avoids being dropped by
Androidβs kernel.
The other option for application logging is to use the
dart:developer
log()
function. This allows you to include a
bit more granularity and information in the logging output.
Hereβs an example:
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 application 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.
import 'dart:convert';
import 'dart:developer' as developer;
void main() {
var myCustomObject = ...;
developer.log(
'log me',
name: 'my.app.category',
error: jsonEncode(myCustomObject),
);
}
If viewing the logging output in DevToolβs logging view, the JSON encoded error param is interpreted as a data object and rendered in the details view for that log entry.
Setting breakpoints
You can insert programmatic breakpoints using the
debugger()
statement. To use this, you have to
import the dart:developer
package at the top of
the relevant file.
The debugger()
statement takes an optional when
argument that you can specify to only break when a
certain condition is true, as in the following example:
import 'dart:developer';
void someFunction(double offset) {
debugger(when: offset > 30.0);
// ...
}
Debug flags: application layers
Each layer of the Flutter framework provides a function to dump its
current 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 in
the middle of running a build phase (in other words, not anywhere inside a
build()
method), if the app has built at least once and is in debug mode
(in other words, any time after calling runApp()
).
For example, the following application:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: AppHome(),
),
);
}
class AppHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Material(
child: Center(
child: TextButton(
onPressed: () {
debugDumpApp();
},
child: Text('Dump App'),
),
),
);
}
}
The previous app outputs something like the following (the precise details vary by the version of the framework, the size of the device, and so forth):
I/flutter ( 6559): WidgetsFlutterBinding - CHECKED MODE
I/flutter ( 6559): RenderObjectToWidgetAdapter<RenderBox>([GlobalObjectKey RenderView(497039273)]; renderObject: RenderView)
I/flutter ( 6559): βMaterialApp(state: _MaterialAppState(1009803148))
I/flutter ( 6559): βScrollConfiguration()
I/flutter ( 6559): βAnimatedTheme(duration: 200ms; state: _AnimatedThemeState(543295893; ticker inactive; ThemeDataTween(ThemeData(Brightness.light Color(0xff2196f3) etc...) β null)))
I/flutter ( 6559): βTheme(ThemeData(Brightness.light Color(0xff2196f3) etc...))
I/flutter ( 6559): βWidgetsApp([GlobalObjectKey _MaterialAppState(1009803148)]; state: _WidgetsAppState(552902158))
I/flutter ( 6559): βCheckedModeBanner()
I/flutter ( 6559): βBanner()
I/flutter ( 6559): βCustomPaint(renderObject: RenderCustomPaint)
I/flutter ( 6559): βDefaultTextStyle(inherit: true; color: Color(0xd0ff0000); family: "monospace"; size: 48.0; weight: 900; decoration: double Color(0xffffff00) TextDecoration.underline)
I/flutter ( 6559): βMediaQuery(MediaQueryData(size: Size(411.4, 683.4), devicePixelRatio: 2.625, textScaleFactor: 1.0, padding: EdgeInsets(0.0, 24.0, 0.0, 0.0)))
I/flutter ( 6559): βLocaleQuery(null)
I/flutter ( 6559): βTitle(color: Color(0xff2196f3))
I/flutter ( 6559): βNavigator([GlobalObjectKey<NavigatorState> _WidgetsAppState(552902158)]; state: NavigatorState(240327618; tracking 1 ticker))
I/flutter ( 6559): βListener(listeners: down, up, cancel; behavior: defer-to-child; renderObject: RenderPointerListener)
I/flutter ( 6559): βAbsorbPointer(renderObject: RenderAbsorbPointer)
I/flutter ( 6559): βFocus([GlobalKey 489139594]; state: _FocusState(739584448))
I/flutter ( 6559): βSemantics(container: true; renderObject: RenderSemanticsAnnotations)
I/flutter ( 6559): β_FocusScope(this scope has focus; focused subscope: [GlobalObjectKey MaterialPageRoute<void>(875520219)])
I/flutter ( 6559): βOverlay([GlobalKey 199833992]; state: OverlayState(619367313; entries: [OverlayEntry@248818791(opaque: false; maintainState: false), OverlayEntry@837336156(opaque: false; maintainState: true)]))
I/flutter ( 6559): β_Theatre(renderObject: _RenderTheatre)
I/flutter ( 6559): βStack(renderObject: RenderStack)
I/flutter ( 6559): β_OverlayEntry([GlobalKey 612888877]; state: _OverlayEntryState(739137453))
I/flutter ( 6559): ββIgnorePointer(ignoring: false; renderObject: RenderIgnorePointer)
I/flutter ( 6559): β βModalBarrier()
I/flutter ( 6559): β βSemantics(container: true; renderObject: RenderSemanticsAnnotations)
I/flutter ( 6559): β βGestureDetector()
I/flutter ( 6559): β βRawGestureDetector(state: RawGestureDetectorState(39068508; gestures: tap; behavior: opaque))
I/flutter ( 6559): β β_GestureSemantics(renderObject: RenderSemanticsGestureHandler)
I/flutter ( 6559): β βListener(listeners: down; behavior: opaque; renderObject: RenderPointerListener)
I/flutter ( 6559): β βConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox)
I/flutter ( 6559): β_OverlayEntry([GlobalKey 727622716]; state: _OverlayEntryState(279971240))
I/flutter ( 6559): β_ModalScope([GlobalKey 816151164]; state: _ModalScopeState(875510645))
I/flutter ( 6559): βFocus([GlobalObjectKey MaterialPageRoute<void>(875520219)]; state: _FocusState(331487674))
I/flutter ( 6559): βSemantics(container: true; renderObject: RenderSemanticsAnnotations)
I/flutter ( 6559): β_FocusScope(this scope has focus)
I/flutter ( 6559): βOffstage(offstage: false; renderObject: RenderOffstage)
I/flutter ( 6559): βIgnorePointer(ignoring: false; renderObject: RenderIgnorePointer)
I/flutter ( 6559): β_MountainViewPageTransition(animation: AnimationController(β 1.000; paused; for MaterialPageRoute<void>(/))β©ProxyAnimationβ©Cubic(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))
I/flutter ( 6559): βSlideTransition(animation: AnimationController(β 1.000; paused; for MaterialPageRoute<void>(/))β©ProxyAnimationβ©Cubic(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))
I/flutter ( 6559): βFractionalTranslation(renderObject: RenderFractionalTranslation)
I/flutter ( 6559): βRepaintBoundary(renderObject: RenderRepaintBoundary)
I/flutter ( 6559): βPageStorage([GlobalKey 619728754])
I/flutter ( 6559): β_ModalScopeStatus(active)
I/flutter ( 6559): βAppHome()
I/flutter ( 6559): βMaterial(MaterialType.canvas; elevation: 0; state: _MaterialState(780114997))
I/flutter ( 6559): βAnimatedContainer(duration: 200ms; has background; state: _AnimatedContainerState(616063822; ticker inactive; has background))
I/flutter ( 6559): βContainer(bg: BoxDecoration())
I/flutter ( 6559): βDecoratedBox(renderObject: RenderDecoratedBox)
I/flutter ( 6559): βContainer(bg: BoxDecoration(backgroundColor: Color(0xfffafafa)))
I/flutter ( 6559): βDecoratedBox(renderObject: RenderDecoratedBox)
I/flutter ( 6559): βNotificationListener<LayoutChangedNotification>()
I/flutter ( 6559): β_InkFeature([GlobalKey ink renderer]; renderObject: _RenderInkFeatures)
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))
I/flutter ( 6559): βDefaultTextStyle(inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 400; baseline: alphabetic)
I/flutter ( 6559): βCenter(alignment: Alignment.center; renderObject: RenderPositionedBox)
I/flutter ( 6559): βTextButton()
I/flutter ( 6559): βMaterialButton(state: _MaterialButtonState(398724090))
I/flutter ( 6559): βConstrainedBox(BoxConstraints(88.0<=w<=Infinity, h=36.0); renderObject: RenderConstrainedBox relayoutBoundary=up1)
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))
I/flutter ( 6559): βDefaultTextStyle(inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 500; baseline: alphabetic)
I/flutter ( 6559): βIconTheme(color: Color(0xdd000000))
I/flutter ( 6559): βInkWell(state: _InkResponseState<InkResponse>(369160267))
I/flutter ( 6559): βGestureDetector()
I/flutter ( 6559): βRawGestureDetector(state: RawGestureDetectorState(175370983; gestures: tap; behavior: opaque))
I/flutter ( 6559): β_GestureSemantics(renderObject: RenderSemanticsGestureHandler relayoutBoundary=up2)
I/flutter ( 6559): βListener(listeners: down; behavior: opaque; renderObject: RenderPointerListener relayoutBoundary=up3)
I/flutter ( 6559): βContainer(padding: EdgeInsets(16.0, 0.0, 16.0, 0.0))
I/flutter ( 6559): βPadding(renderObject: RenderPadding relayoutBoundary=up4)
I/flutter ( 6559): βCenter(alignment: Alignment.center; widthFactor: 1.0; renderObject: RenderPositionedBox relayoutBoundary=up5)
I/flutter ( 6559): βText("Dump App")
I/flutter ( 6559): βRichText(renderObject: RenderParagraph relayoutBoundary=up6)
This is the βflattenedβ tree, showing all the widgets projected
through their various build functions. (This is the tree you obtain if
you call toStringDeep()
on the root of the widget tree.)
Youβll see a lot of widgets in there that donβt appear in your
applicationβs source, because they are inserted by the frameworkβs
widgetsβ build functions. For example,
InkFeature
is an implementation detail of the Material
widget.
Since the debugDumpApp()
call is invoked when the button changes
from being pressed to being released, it coincides with the
TextButton
object calling setState()
and thus marking itself dirty. That is why, when you look at the dump you
should see that specific object marked as βdirtyβ. You can also see what
gesture listeners have been registered; in this case, a single
GestureDetector is listed, and it is listening only to a βtapβ gesture
(βtapβ is the output of a TapGestureDetector
βs toStringShort
function).
If you write your own widgets, you can add information by overriding
debugFillProperties()
. Add DiagnosticsProperty
objects to the methodβs argument, and call the superclass method.
This function is what the toString
method uses to fill in the
widgetβs description.
Render tree
If you are trying to debug a layout issue, then the Widgets layerβs
tree might be insufficiently detailed. In that case, you can dump the
rendering tree by calling debugDumpRenderTree()
.
As with debugDumpApp()
, you can call this more or less any time
except during a layout or paint phase. As a general rule,
calling it from a frame callback
or 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 like the following:
I/flutter ( 6559): RenderView
I/flutter ( 6559): β debug mode enabled - android
I/flutter ( 6559): β window size: Size(1080.0, 1794.0) (in physical pixels)
I/flutter ( 6559): β device pixel ratio: 2.625 (physical pixels per logical pixel)
I/flutter ( 6559): β configuration: Size(411.4, 683.4) at 2.625x (in logical pixels)
I/flutter ( 6559): β
I/flutter ( 6559): ββchild: RenderCustomPaint
I/flutter ( 6559): β creator: CustomPaint β Banner β CheckedModeBanner β
I/flutter ( 6559): β WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)] β
I/flutter ( 6559): β Theme β AnimatedTheme β ScrollConfiguration β MaterialApp β
I/flutter ( 6559): β [root]
I/flutter ( 6559): β parentData: <none>
I/flutter ( 6559): β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β size: Size(411.4, 683.4)
I/flutter ( 6559): β
I/flutter ( 6559): ββchild: RenderPointerListener
I/flutter ( 6559): β creator: Listener β Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559): β _WidgetsAppState(552902158)] β Title β LocaleQuery β MediaQuery
I/flutter ( 6559): β β DefaultTextStyle β CustomPaint β Banner β CheckedModeBanner β
I/flutter ( 6559): β WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)] β
I/flutter ( 6559): β Theme β AnimatedTheme β β―
I/flutter ( 6559): β parentData: <none>
I/flutter ( 6559): β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β size: Size(411.4, 683.4)
I/flutter ( 6559): β behavior: defer-to-child
I/flutter ( 6559): β listeners: down, up, cancel
I/flutter ( 6559): β
I/flutter ( 6559): ββchild: RenderAbsorbPointer
I/flutter ( 6559): β creator: AbsorbPointer β Listener β
I/flutter ( 6559): β Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559): β _WidgetsAppState(552902158)] β Title β LocaleQuery β MediaQuery
I/flutter ( 6559): β β DefaultTextStyle β CustomPaint β Banner β CheckedModeBanner β
I/flutter ( 6559): β WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)] β
I/flutter ( 6559): β Theme β β―
I/flutter ( 6559): β parentData: <none>
I/flutter ( 6559): β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β size: Size(411.4, 683.4)
I/flutter ( 6559): β absorbing: false
I/flutter ( 6559): β
I/flutter ( 6559): ββchild: RenderSemanticsAnnotations
I/flutter ( 6559): β creator: Semantics β Focus-[GlobalKey 489139594] β AbsorbPointer
I/flutter ( 6559): β β Listener β Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559): β _WidgetsAppState(552902158)] β Title β LocaleQuery β MediaQuery
I/flutter ( 6559): β β DefaultTextStyle β CustomPaint β Banner β CheckedModeBanner β
I/flutter ( 6559): β β―
I/flutter ( 6559): β parentData: <none>
I/flutter ( 6559): β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β size: Size(411.4, 683.4)
I/flutter ( 6559): β
I/flutter ( 6559): ββchild: _RenderTheatre
I/flutter ( 6559): β creator: _Theatre β Overlay-[GlobalKey 199833992] β _FocusScope β
I/flutter ( 6559): β Semantics β Focus-[GlobalKey 489139594] β AbsorbPointer β
I/flutter ( 6559): β Listener β Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559): β _WidgetsAppState(552902158)] β Title β LocaleQuery β MediaQuery
I/flutter ( 6559): β β DefaultTextStyle β β―
I/flutter ( 6559): β parentData: <none>
I/flutter ( 6559): β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β size: Size(411.4, 683.4)
I/flutter ( 6559): β
I/flutter ( 6559): ββonstage: RenderStack
I/flutter ( 6559): β β creator: Stack β _Theatre β Overlay-[GlobalKey 199833992] β
I/flutter ( 6559): β β _FocusScope β Semantics β Focus-[GlobalKey 489139594] β
I/flutter ( 6559): β β AbsorbPointer β Listener β
I/flutter ( 6559): β β Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559): β β _WidgetsAppState(552902158)] β Title β LocaleQuery β MediaQuery
I/flutter ( 6559): β β β β―
I/flutter ( 6559): β β parentData: not positioned; offset=Offset(0.0, 0.0)
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild 1: RenderIgnorePointer
I/flutter ( 6559): β β β creator: IgnorePointer β _OverlayEntry-[GlobalKey 612888877] β
I/flutter ( 6559): β β β Stack β _Theatre β Overlay-[GlobalKey 199833992] β _FocusScope
I/flutter ( 6559): β β β β Semantics β Focus-[GlobalKey 489139594] β AbsorbPointer β
I/flutter ( 6559): β β β Listener β Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559): β β β _WidgetsAppState(552902158)] β Title β β―
I/flutter ( 6559): β β β parentData: not positioned; offset=Offset(0.0, 0.0)
I/flutter ( 6559): β β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β β ignoring: false
I/flutter ( 6559): β β β ignoringSemantics: implicitly false
I/flutter ( 6559): β β β
I/flutter ( 6559): β β ββchild: RenderSemanticsAnnotations
I/flutter ( 6559): β β β creator: Semantics β ModalBarrier β IgnorePointer β
I/flutter ( 6559): β β β _OverlayEntry-[GlobalKey 612888877] β Stack β _Theatre β
I/flutter ( 6559): β β β Overlay-[GlobalKey 199833992] β _FocusScope β Semantics β
I/flutter ( 6559): β β β Focus-[GlobalKey 489139594] β AbsorbPointer β Listener β β―
I/flutter ( 6559): β β β parentData: <none>
I/flutter ( 6559): β β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β β
I/flutter ( 6559): β β ββchild: RenderSemanticsGestureHandler
I/flutter ( 6559): β β β creator: _GestureSemantics β RawGestureDetector β GestureDetector
I/flutter ( 6559): β β β β Semantics β ModalBarrier β IgnorePointer β
I/flutter ( 6559): β β β _OverlayEntry-[GlobalKey 612888877] β Stack β _Theatre β
I/flutter ( 6559): β β β Overlay-[GlobalKey 199833992] β _FocusScope β Semantics β β―
I/flutter ( 6559): β β β parentData: <none>
I/flutter ( 6559): β β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β β
I/flutter ( 6559): β β ββchild: RenderPointerListener
I/flutter ( 6559): β β β creator: Listener β _GestureSemantics β RawGestureDetector β
I/flutter ( 6559): β β β GestureDetector β Semantics β ModalBarrier β IgnorePointer β
I/flutter ( 6559): β β β _OverlayEntry-[GlobalKey 612888877] β Stack β _Theatre β
I/flutter ( 6559): β β β Overlay-[GlobalKey 199833992] β _FocusScope β β―
I/flutter ( 6559): β β β parentData: <none>
I/flutter ( 6559): β β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β β behavior: opaque
I/flutter ( 6559): β β β listeners: down
I/flutter ( 6559): β β β
I/flutter ( 6559): β β ββchild: RenderConstrainedBox
I/flutter ( 6559): β β creator: ConstrainedBox β Listener β _GestureSemantics β
I/flutter ( 6559): β β RawGestureDetector β GestureDetector β Semantics β ModalBarrier
I/flutter ( 6559): β β β IgnorePointer β _OverlayEntry-[GlobalKey 612888877] β Stack β
I/flutter ( 6559): β β _Theatre β Overlay-[GlobalKey 199833992] β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β additionalConstraints: BoxConstraints(biggest)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild 2: RenderSemanticsAnnotations
I/flutter ( 6559): β β creator: Semantics β Focus-[GlobalObjectKey
I/flutter ( 6559): β β MaterialPageRoute<void>(875520219)] β _ModalScope-[GlobalKey
I/flutter ( 6559): β β 816151164] β _OverlayEntry-[GlobalKey 727622716] β Stack β
I/flutter ( 6559): β β _Theatre β Overlay-[GlobalKey 199833992] β _FocusScope β
I/flutter ( 6559): β β Semantics β Focus-[GlobalKey 489139594] β AbsorbPointer β
I/flutter ( 6559): β β Listener β β―
I/flutter ( 6559): β β parentData: not positioned; offset=Offset(0.0, 0.0)
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderOffstage
I/flutter ( 6559): β β creator: Offstage β _FocusScope β Semantics β
I/flutter ( 6559): β β Focus-[GlobalObjectKey MaterialPageRoute<void>(875520219)] β
I/flutter ( 6559): β β _ModalScope-[GlobalKey 816151164] β _OverlayEntry-[GlobalKey
I/flutter ( 6559): β β 727622716] β Stack β _Theatre β Overlay-[GlobalKey 199833992] β
I/flutter ( 6559): β β _FocusScope β Semantics β Focus-[GlobalKey 489139594] β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β offstage: false
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderIgnorePointer
I/flutter ( 6559): β β creator: IgnorePointer β Offstage β _FocusScope β Semantics β
I/flutter ( 6559): β β Focus-[GlobalObjectKey MaterialPageRoute<void>(875520219)] β
I/flutter ( 6559): β β _ModalScope-[GlobalKey 816151164] β _OverlayEntry-[GlobalKey
I/flutter ( 6559): β β 727622716] β Stack β _Theatre β Overlay-[GlobalKey 199833992] β
I/flutter ( 6559): β β _FocusScope β Semantics β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β ignoring: false
I/flutter ( 6559): β β ignoringSemantics: implicitly false
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderFractionalTranslation
I/flutter ( 6559): β β creator: FractionalTranslation β SlideTransition β
I/flutter ( 6559): β β _MountainViewPageTransition β IgnorePointer β Offstage β
I/flutter ( 6559): β β _FocusScope β Semantics β Focus-[GlobalObjectKey
I/flutter ( 6559): β β MaterialPageRoute<void>(875520219)] β _ModalScope-[GlobalKey
I/flutter ( 6559): β β 816151164] β _OverlayEntry-[GlobalKey 727622716] β Stack β
I/flutter ( 6559): β β _Theatre β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β translation: Offset(0.0, 0.0)
I/flutter ( 6559): β β transformHitTests: true
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderRepaintBoundary
I/flutter ( 6559): β β creator: RepaintBoundary β FractionalTranslation β
I/flutter ( 6559): β β SlideTransition β _MountainViewPageTransition β IgnorePointer β
I/flutter ( 6559): β β Offstage β _FocusScope β Semantics β Focus-[GlobalObjectKey
I/flutter ( 6559): β β MaterialPageRoute<void>(875520219)] β _ModalScope-[GlobalKey
I/flutter ( 6559): β β 816151164] β _OverlayEntry-[GlobalKey 727622716] β Stack β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β metrics: 83.3% useful (1 bad vs 5 good)
I/flutter ( 6559): β β diagnosis: this is a useful repaint boundary and should be kept
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderDecoratedBox
I/flutter ( 6559): β β creator: DecoratedBox β Container β AnimatedContainer β Material
I/flutter ( 6559): β β β AppHome β _ModalScopeStatus β PageStorage-[GlobalKey
I/flutter ( 6559): β β 619728754] β RepaintBoundary β FractionalTranslation β
I/flutter ( 6559): β β SlideTransition β _MountainViewPageTransition β IgnorePointer β
I/flutter ( 6559): β β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β decoration:
I/flutter ( 6559): β β <no decorations specified>
I/flutter ( 6559): β β configuration: ImageConfiguration(bundle:
I/flutter ( 6559): β β PlatformAssetBundle@367106502(), devicePixelRatio: 2.625,
I/flutter ( 6559): β β platform: android)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderDecoratedBox
I/flutter ( 6559): β β creator: DecoratedBox β Container β DecoratedBox β Container β
I/flutter ( 6559): β β AnimatedContainer β Material β AppHome β _ModalScopeStatus β
I/flutter ( 6559): β β PageStorage-[GlobalKey 619728754] β RepaintBoundary β
I/flutter ( 6559): β β FractionalTranslation β SlideTransition β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β decoration:
I/flutter ( 6559): β β backgroundColor: Color(0xfffafafa)
I/flutter ( 6559): β β configuration: ImageConfiguration(bundle:
I/flutter ( 6559): β β PlatformAssetBundle@367106502(), devicePixelRatio: 2.625,
I/flutter ( 6559): β β platform: android)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: _RenderInkFeatures
I/flutter ( 6559): β β creator: _InkFeature-[GlobalKey ink renderer] β
I/flutter ( 6559): β β NotificationListener<LayoutChangedNotification> β DecoratedBox
I/flutter ( 6559): β β β Container β DecoratedBox β Container β AnimatedContainer β
I/flutter ( 6559): β β Material β AppHome β _ModalScopeStatus β PageStorage-[GlobalKey
I/flutter ( 6559): β β 619728754] β RepaintBoundary β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderPositionedBox
I/flutter ( 6559): β β creator: Center β DefaultTextStyle β AnimatedDefaultTextStyle β
I/flutter ( 6559): β β _InkFeature-[GlobalKey ink renderer] β
I/flutter ( 6559): β β NotificationListener<LayoutChangedNotification> β DecoratedBox
I/flutter ( 6559): β β β Container β DecoratedBox β Container β AnimatedContainer β
I/flutter ( 6559): β β Material β AppHome β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559): β β size: Size(411.4, 683.4)
I/flutter ( 6559): β β alignment: Alignment.center
I/flutter ( 6559): β β widthFactor: expand
I/flutter ( 6559): β β heightFactor: expand
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderConstrainedBox relayoutBoundary=up1
I/flutter ( 6559): β β creator: ConstrainedBox β MaterialButton β TextButton β Center β
I/flutter ( 6559): β β DefaultTextStyle β AnimatedDefaultTextStyle β
I/flutter ( 6559): β β _InkFeature-[GlobalKey ink renderer] β
I/flutter ( 6559): β β NotificationListener<LayoutChangedNotification> β DecoratedBox
I/flutter ( 6559): β β β Container β DecoratedBox β Container β β―
I/flutter ( 6559): β β parentData: offset=Offset(156.7, 323.7)
I/flutter ( 6559): β β constraints: BoxConstraints(0.0<=w<=411.4, 0.0<=h<=683.4)
I/flutter ( 6559): β β size: Size(98.0, 36.0)
I/flutter ( 6559): β β additionalConstraints: BoxConstraints(88.0<=w<=Infinity, h=36.0)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderSemanticsGestureHandler relayoutBoundary=up2
I/flutter ( 6559): β β creator: _GestureSemantics β RawGestureDetector β GestureDetector
I/flutter ( 6559): β β β InkWell β IconTheme β DefaultTextStyle β
I/flutter ( 6559): β β AnimatedDefaultTextStyle β ConstrainedBox β MaterialButton β
I/flutter ( 6559): β β TextButton β Center β DefaultTextStyle β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
I/flutter ( 6559): β β size: Size(98.0, 36.0)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderPointerListener relayoutBoundary=up3
I/flutter ( 6559): β β creator: Listener β _GestureSemantics β RawGestureDetector β
I/flutter ( 6559): β β GestureDetector β InkWell β IconTheme β DefaultTextStyle β
I/flutter ( 6559): β β AnimatedDefaultTextStyle β ConstrainedBox β MaterialButton β
I/flutter ( 6559): β β TextButton β Center β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
I/flutter ( 6559): β β size: Size(98.0, 36.0)
I/flutter ( 6559): β β behavior: opaque
I/flutter ( 6559): β β listeners: down
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderPadding relayoutBoundary=up4
I/flutter ( 6559): β β creator: Padding β Container β Listener β _GestureSemantics β
I/flutter ( 6559): β β RawGestureDetector β GestureDetector β InkWell β IconTheme β
I/flutter ( 6559): β β DefaultTextStyle β AnimatedDefaultTextStyle β ConstrainedBox β
I/flutter ( 6559): β β MaterialButton β β―
I/flutter ( 6559): β β parentData: <none>
I/flutter ( 6559): β β constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
I/flutter ( 6559): β β size: Size(98.0, 36.0)
I/flutter ( 6559): β β padding: EdgeInsets(16.0, 0.0, 16.0, 0.0)
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderPositionedBox relayoutBoundary=up5
I/flutter ( 6559): β β creator: Center β Padding β Container β Listener β
I/flutter ( 6559): β β _GestureSemantics β RawGestureDetector β GestureDetector β
I/flutter ( 6559): β β InkWell β IconTheme β DefaultTextStyle β
I/flutter ( 6559): β β AnimatedDefaultTextStyle β ConstrainedBox β β―
I/flutter ( 6559): β β parentData: offset=Offset(16.0, 0.0)
I/flutter ( 6559): β β constraints: BoxConstraints(56.0<=w<=379.4, h=36.0)
I/flutter ( 6559): β β size: Size(66.0, 36.0)
I/flutter ( 6559): β β alignment: Alignment.center
I/flutter ( 6559): β β widthFactor: 1.0
I/flutter ( 6559): β β heightFactor: expand
I/flutter ( 6559): β β
I/flutter ( 6559): β ββchild: RenderParagraph relayoutBoundary=up6
I/flutter ( 6559): β β creator: RichText β Text β Center β Padding β Container β
I/flutter ( 6559): β β Listener β _GestureSemantics β RawGestureDetector β
I/flutter ( 6559): β β GestureDetector β InkWell β IconTheme β DefaultTextStyle β β―
I/flutter ( 6559): β β parentData: offset=Offset(0.0, 10.0)
I/flutter ( 6559): β β constraints: BoxConstraints(0.0<=w<=379.4, 0.0<=h<=36.0)
I/flutter ( 6559): β β size: Size(66.0, 16.0)
I/flutter ( 6559): β βββ¦ββ text βββ
I/flutter ( 6559): β β TextSpan:
I/flutter ( 6559): β β inherit: false
I/flutter ( 6559): β β color: Color(0xdd000000)
I/flutter ( 6559): β β family: "Roboto"
I/flutter ( 6559): β β size: 14.0
I/flutter ( 6559): β β weight: 500
I/flutter ( 6559): β β baseline: alphabetic
I/flutter ( 6559): β β "Dump App"
I/flutter ( 6559): β ββββββββββββ
I/flutter ( 6559): β
I/flutter ( 6559): ββno offstage children
This is the output of the root RenderObject
objectβs
toStringDeep()
function.
When debugging layout issues, the key fields to look at are the
size
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 the
RenderPositionedBox
to be the size of the screen, with
constraints of BoxConstraints(w=411.4, h=683.4)
.
The RenderPositionedBox
, which the dump says was created by a
Center
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, a
RenderPadding
, further inserts these constraints to ensure
there 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 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.)
The inner-most RenderPositionedBox
loosens the constraints again,
this time to center the text within the button. The
RenderParagraph
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 the
width of all the boxes that form the button, as they all take their
childβ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 how
many 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 be
affected by the new dimensions.
If you write your own render objects, you can add information to the
dump by overriding debugFillProperties()
.
Add DiagnosticsProperty
objects to the methodβs argument, and call the superclass method.
Layer tree
If you are trying to debug a compositing issue, you can use
debugDumpLayerTree()
.
For the previous example, it would output:
I/flutter : TransformLayer
I/flutter : β creator: [root]
I/flutter : β offset: Offset(0.0, 0.0)
I/flutter : β transform:
I/flutter : β [0] 3.5,0.0,0.0,0.0
I/flutter : β [1] 0.0,3.5,0.0,0.0
I/flutter : β [2] 0.0,0.0,1.0,0.0
I/flutter : β [3] 0.0,0.0,0.0,1.0
I/flutter : β
I/flutter : ββchild 1: OffsetLayer
I/flutter : β β creator: RepaintBoundary β _FocusScope β Semantics β Focus-[GlobalObjectKey MaterialPageRoute(560156430)] β _ModalScope-[GlobalKey 328026813] β _OverlayEntry-[GlobalKey 388965355] β Stack β Overlay-[GlobalKey 625702218] β Navigator-[GlobalObjectKey _MaterialAppState(859106034)] β Title β β―
I/flutter : β β offset: Offset(0.0, 0.0)
I/flutter : β β
I/flutter : β ββchild 1: PictureLayer
I/flutter : β
I/flutter : ββchild 2: PictureLayer
This is the output of calling toStringDeep
on the root Layer
object.
The transform at the root is the transform that applies the device pixel ratio; in this case, a ratio of 3.5 device pixels for every logical pixel.
The RepaintBoundary
widget, which creates a RenderRepaintBoundary
in the render tree, creates a new layer in the layer tree. This is
used 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) using
debugDumpSemanticsTree()
. To use this,
you have to have first enable accessibility, for example, by
enabling a system accessibility tool or the SemanticsDebugger
.
For the previous example, it would output the following:
I/flutter : SemanticsNode(0; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter : βSemanticsNode(1; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter : β βSemanticsNode(2; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4); canBeTapped)
I/flutter : βSemanticsNode(3; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter : βSemanticsNode(4; Rect.fromLTRB(0.0, 0.0, 82.0, 36.0); canBeTapped; "Dump App")
Scheduling
To find out where your events happen relative to the frameβs
begin/end, you can toggle the debugPrintBeginFrameBanner
and the debugPrintEndFrameBanner
booleans to print the
beginning and end of the frames to the console.
For example:
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 : ββββββββββββββββββββββββββββββββββββββββββββββββββββ
The debugPrintScheduleFrameStacks
flag can also be used
to print the call stack causing the current frame to be scheduled.
Debug flags: layout
You can also debug a layout problem visually, by setting
debugPaintSizeEnabled
to true
.
This is a boolean from the rendering
library. It can be
enabled 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:
//add import to rendering library
import 'package:flutter/rendering.dart';
void main() {
debugPaintSizeEnabled=true;
runApp(MyApp());
}
When it is enabled, all boxes get a bright teal border,
padding (from widgets like Padding
) is shown in faded
blue with a darker blue box around the child, alignment
(from widgets like Center
and Align
) is shown with
yellow arrows, and spacers (from widgets like
Container
when they have no child) are shown in gray.
The debugPaintBaselinesEnabled
flag
does something similar but for objects with baselines.
The alphabetic baseline is shown in bright green and the
ideographic baseline in orange.
The debugPaintPointersEnabled
flag turns on a
special mode whereby any objects that are being tapped
get highlighted in teal. This can help you determine
whether an object is somehow failing to correctly hit
test (which might happen if, for instance, it is actually
outside the bounds of its parent and thus not
being considered for hit testing in the first place).
If youβre trying to debug compositor layers, for example
to determine whether and where to add RepaintBoundary
widgets, you can use the debugPaintLayerBordersEnabled
flag, which outlines each layerβs bounds in orange,
or the debugRepaintRainbowEnabled
flag,
which causes layers to be overlayed with a rotating set of
colors 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
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 flags: performance
Flutter provides a wide variety of debug flags and functions to help you debug your app at various points along the development cycle. To use these features, you must compile in debug mode. The following list, while not complete, highlights some of flags (and one function) from the rendering 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 your
main()
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 Highlight Repaints 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 thedebugPrintStack()
method from theservices
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 thedebugPrintStack()
method from theservices
library to print your own stack traces on demand, if this kind of approach is useful to you.To perform custom performance traces programmatically and measure wall/CPU time of arbitrary segments of Dart code similar to what would be done on Android with systrace, use
dart:developer
Timeline utilities to wrap the code you want to measure such as:import 'dart:developer'; Timeline.startSync('interesting function'); // iWonderHowLongThisTakes(); 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 records of your app in Chromeβs tracing tool.
Be sure to run your app in profile mode to ensure that the runtime performance characteristics closely match that of your final product.
You can programmatically enable the PerformanceOverlay widget by setting the
showPerformanceOverlay
property totrue
on theMaterialApp
,CupertinoApp
, orWidgetsApp
constructor:class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( showPerformanceOverlay: true, title: 'My Awesome App', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'My Awesome App'), ); } }
(If youβre not using
MaterialApp
,CupertinoApp
, orWidgetsApp
, you can get the same effect by wrapping your application in a stack and putting a widget on your stack that was created by callingPerformanceOverlay.allEnabled()
.)For information on how to interpret the graphs in the overlay, see The performance overlay in Profiling Flutter performance.
You can programmatically overlay a Material Design baseline grid on top of your app to help verify alignments by using the
debugShowMaterialGrid
argument in theMaterialApp
constructor.In non-Material applications, you can achieve a similar effect by using a
GridPaper
widget directly.