diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 987c0a50b8135..ff77ca58d37ff 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -153,7 +153,6 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture }; }, ); - registerServiceExtension( name: 'debugDumpSemanticsTreeInTraversalOrder', callback: (Map parameters) async { @@ -164,7 +163,6 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture }; }, ); - registerServiceExtension( name: 'debugDumpSemanticsTreeInInverseHitTestOrder', callback: (Map parameters) async { @@ -175,6 +173,22 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture }; }, ); + registerBoolServiceExtension( + name: 'profileRenderObjectPaints', + getter: () async => debugProfilePaintsEnabled, + setter: (bool value) async { + if (debugProfilePaintsEnabled != value) + debugProfilePaintsEnabled = value; + }, + ); + registerBoolServiceExtension( + name: 'profileRenderObjectLayouts', + getter: () async => debugProfileLayoutsEnabled, + setter: (bool value) async { + if (debugProfileLayoutsEnabled != value) + debugProfileLayoutsEnabled = value; + }, + ); } } diff --git a/packages/flutter/lib/src/rendering/debug.dart b/packages/flutter/lib/src/rendering/debug.dart index 59214ae80f4f9..724190f857eb1 100644 --- a/packages/flutter/lib/src/rendering/debug.dart +++ b/packages/flutter/lib/src/rendering/debug.dart @@ -111,9 +111,8 @@ bool debugProfileLayoutsEnabled = false; /// Adds [dart:developer.Timeline] events for every [RenderObject] painted. /// -/// This is only enabled in debug builds. The timing information this exposes is -/// not representative of actual paints. However, it can expose unexpected -/// painting in the timeline. +/// The timing information this flag exposes is not representative of actual +/// paints. However, it can expose unexpected painting in the timeline. /// /// For details on how to use [dart:developer.Timeline] events in the Dart /// Observatory to optimize your app, see: diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index da3929a1971f4..dd4248f1cfc22 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -175,9 +175,9 @@ class PaintingContext extends ClipContext { /// into the layer subtree associated with this painting context. Otherwise, /// the child will be painted into the current PictureLayer for this context. void paintChild(RenderObject child, Offset offset) { + if (!kReleaseMode && debugProfilePaintsEnabled) + Timeline.startSync('${child.runtimeType}', arguments: timelineArgumentsIndicatingLandmarkEvent); assert(() { - if (debugProfilePaintsEnabled) - Timeline.startSync('${child.runtimeType}', arguments: timelineArgumentsIndicatingLandmarkEvent); debugOnProfilePaint?.call(child); return true; }()); @@ -189,11 +189,8 @@ class PaintingContext extends ClipContext { child._paintWithContext(this, offset); } - assert(() { - if (debugProfilePaintsEnabled) - Timeline.finishSync(); - return true; - }()); + if (!kReleaseMode && debugProfilePaintsEnabled) + Timeline.finishSync(); } void _compositeChild(RenderObject child, Offset offset) { diff --git a/packages/flutter/test/foundation/service_extensions_test.dart b/packages/flutter/test/foundation/service_extensions_test.dart index c0a6806b6b319..0d680878e0733 100644 --- a/packages/flutter/test/foundation/service_extensions_test.dart +++ b/packages/flutter/test/foundation/service_extensions_test.dart @@ -173,7 +173,7 @@ void main() { const int disabledExtensions = kIsWeb ? 2 : 0; // If you add a service extension... TEST IT! :-) // ...then increment this number. - expect(binding.extensions.length, 33 + widgetInspectorExtensionCount - disabledExtensions); + expect(binding.extensions.length, 35 + widgetInspectorExtensionCount - disabledExtensions); expect(console, isEmpty); debugPrint = debugPrintThrottled; @@ -442,6 +442,64 @@ void main() { expect(binding.frameScheduled, isFalse); }); + test('Service extensions - profileRenderObjectPaints', () async { + Map result; + + expect(binding.frameScheduled, isFalse); + expect(debugProfileBuildsEnabled, false); + + result = await binding.testExtension('profileRenderObjectPaints', {}); + expect(result, {'enabled': 'false'}); + expect(debugProfilePaintsEnabled, false); + + result = await binding.testExtension('profileRenderObjectPaints', {'enabled': 'true'}); + expect(result, {'enabled': 'true'}); + expect(debugProfilePaintsEnabled, true); + + result = await binding.testExtension('profileRenderObjectPaints', {}); + expect(result, {'enabled': 'true'}); + expect(debugProfilePaintsEnabled, true); + + result = await binding.testExtension('profileRenderObjectPaints', {'enabled': 'false'}); + expect(result, {'enabled': 'false'}); + expect(debugProfilePaintsEnabled, false); + + result = await binding.testExtension('profileRenderObjectPaints', {}); + expect(result, {'enabled': 'false'}); + expect(debugProfilePaintsEnabled, false); + + expect(binding.frameScheduled, isFalse); + }); + + test('Service extensions - profileRenderObjectLayouts', () async { + Map result; + + expect(binding.frameScheduled, isFalse); + expect(debugProfileLayoutsEnabled, false); + + result = await binding.testExtension('profileRenderObjectLayouts', {}); + expect(result, {'enabled': 'false'}); + expect(debugProfileLayoutsEnabled, false); + + result = await binding.testExtension('profileRenderObjectLayouts', {'enabled': 'true'}); + expect(result, {'enabled': 'true'}); + expect(debugProfileLayoutsEnabled, true); + + result = await binding.testExtension('profileRenderObjectLayouts', {}); + expect(result, {'enabled': 'true'}); + expect(debugProfileLayoutsEnabled, true); + + result = await binding.testExtension('profileRenderObjectLayouts', {'enabled': 'false'}); + expect(result, {'enabled': 'false'}); + expect(debugProfileLayoutsEnabled, false); + + result = await binding.testExtension('profileRenderObjectLayouts', {}); + expect(result, {'enabled': 'false'}); + expect(debugProfileLayoutsEnabled, false); + + expect(binding.frameScheduled, isFalse); + }); + test('Service extensions - evict', () async { Map result; bool completed;