Unverified Commit ac095ed3 authored by Daniel Chevalier's avatar Daniel Chevalier Committed by GitHub

Changes WidgetInspector to use valuenotifier instead of a force rebuild for (#131634)

![](https://media.giphy.com/media/qriH9W51oLsL6/giphy.gif)
Fixes https://github.com/flutter/devtools/issues/6014

Change the forceRebuild behaviour of the WidgetInspector to use
ValueListenableBuilders instead. This should help resolve heavy rebuilds
when the widgetInspectorOverride value changes.
parent be45c4ca
...@@ -31,6 +31,7 @@ import 'shortcuts.dart'; ...@@ -31,6 +31,7 @@ import 'shortcuts.dart';
import 'tap_region.dart'; import 'tap_region.dart';
import 'text.dart'; import 'text.dart';
import 'title.dart'; import 'title.dart';
import 'value_listenable_builder.dart';
import 'widget_inspector.dart'; import 'widget_inspector.dart';
export 'dart:ui' show Locale; export 'dart:ui' show Locale;
...@@ -1189,13 +1190,22 @@ class WidgetsApp extends StatefulWidget { ...@@ -1189,13 +1190,22 @@ class WidgetsApp extends StatefulWidget {
/// If true, forces the widget inspector to be visible. /// If true, forces the widget inspector to be visible.
/// ///
/// Overrides the `debugShowWidgetInspector` value set in [WidgetsApp].
///
/// Used by the `debugShowWidgetInspector` debugging extension. /// Used by the `debugShowWidgetInspector` debugging extension.
/// ///
/// The inspector allows you to select a location on your device or emulator /// The inspector allows the selection of a location on your device or emulator
/// and view what widgets and render objects associated with it. An outline of /// and view what widgets and render objects associated with it. An outline of
/// the selected widget and some summary information is shown on device and /// the selected widget and some summary information is shown on device and
/// more detailed information is shown in the IDE or DevTools. /// more detailed information is shown in the IDE or DevTools.
static bool debugShowWidgetInspectorOverride = false; static bool get debugShowWidgetInspectorOverride {
return _debugShowWidgetInspectorOverrideNotifier.value;
}
static set debugShowWidgetInspectorOverride(bool value) {
_debugShowWidgetInspectorOverrideNotifier.value = value;
}
static final ValueNotifier<bool> _debugShowWidgetInspectorOverrideNotifier = ValueNotifier<bool>(false);
/// If false, prevents the debug banner from being visible. /// If false, prevents the debug banner from being visible.
/// ///
...@@ -1743,12 +1753,19 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver { ...@@ -1743,12 +1753,19 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
} }
assert(() { assert(() {
if (widget.debugShowWidgetInspector || WidgetsApp.debugShowWidgetInspectorOverride) { result = ValueListenableBuilder<bool>(
result = WidgetInspector( valueListenable: WidgetsApp._debugShowWidgetInspectorOverrideNotifier,
selectButtonBuilder: widget.inspectorSelectButtonBuilder, builder: (BuildContext context, bool debugShowWidgetInspectorOverride, Widget? child) {
child: result, if (widget.debugShowWidgetInspector || debugShowWidgetInspectorOverride) {
); return WidgetInspector(
} selectButtonBuilder: widget.inspectorSelectButtonBuilder,
child: child!,
);
}
return child!;
},
child: result,
);
if (widget.debugShowCheckedModeBanner && WidgetsApp.debugAllowBannerOverride) { if (widget.debugShowCheckedModeBanner && WidgetsApp.debugAllowBannerOverride) {
result = CheckedModeBanner( result = CheckedModeBanner(
child: result, child: result,
......
...@@ -1078,11 +1078,10 @@ mixin WidgetInspectorService { ...@@ -1078,11 +1078,10 @@ mixin WidgetInspectorService {
name: WidgetInspectorServiceExtensions.show.name, name: WidgetInspectorServiceExtensions.show.name,
getter: () async => WidgetsApp.debugShowWidgetInspectorOverride, getter: () async => WidgetsApp.debugShowWidgetInspectorOverride,
setter: (bool value) { setter: (bool value) {
if (WidgetsApp.debugShowWidgetInspectorOverride == value) { if (WidgetsApp.debugShowWidgetInspectorOverride != value) {
return Future<void>.value(); WidgetsApp.debugShowWidgetInspectorOverride = value;
} }
WidgetsApp.debugShowWidgetInspectorOverride = value; return Future<void>.value();
return forceRebuild();
}, },
registerExtension: registerExtension, registerExtension: registerExtension,
); );
......
...@@ -4115,6 +4115,28 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4115,6 +4115,28 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
testWidgetsWithLeakTracking('ext.flutter.inspector.show', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.show', (WidgetTester tester) async {
final Iterable<Map<Object, Object?>> extensionChangedEvents = service.getServiceExtensionStateChangedEvents('ext.flutter.inspector.show'); final Iterable<Map<Object, Object?>> extensionChangedEvents = service.getServiceExtensionStateChangedEvents('ext.flutter.inspector.show');
Map<Object, Object?> extensionChangedEvent; Map<Object, Object?> extensionChangedEvent;
int debugShowChangeCounter = 0;
final GlobalKey key = GlobalKey();
await tester.pumpWidget(
WidgetsApp(
key: key,
builder: (BuildContext context, Widget? child) {
return const Placeholder();
},
color: const Color(0xFF123456),
),
);
final ValueListenableBuilder<bool> valueListenableBuilderWidget = tester.widget(
find.byType(ValueListenableBuilder<bool>),
);
void debugShowWidgetInspectorOverrideCallback() {
debugShowChangeCounter++;
}
WidgetsApp.debugShowWidgetInspectorOverride = false;
valueListenableBuilderWidget.valueListenable.addListener(debugShowWidgetInspectorOverrideCallback);
service.rebuildCount = 0; service.rebuildCount = 0;
expect(extensionChangedEvents, isEmpty); expect(extensionChangedEvents, isEmpty);
...@@ -4129,7 +4151,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4129,7 +4151,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
extensionChangedEvent = extensionChangedEvents.last; extensionChangedEvent = extensionChangedEvents.last;
expect(extensionChangedEvent['extension'], equals('ext.flutter.inspector.show')); expect(extensionChangedEvent['extension'], equals('ext.flutter.inspector.show'));
expect(extensionChangedEvent['value'], isTrue); expect(extensionChangedEvent['value'], isTrue);
expect(service.rebuildCount, equals(1)); expect(service.rebuildCount, equals(0)); // Should not be force rebuilt.
expect(debugShowChangeCounter, equals(1));
expect( expect(
await service.testBoolExtension( await service.testBoolExtension(
WidgetInspectorServiceExtensions.show.name, WidgetInspectorServiceExtensions.show.name,
...@@ -4139,6 +4162,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4139,6 +4162,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
expect(WidgetsApp.debugShowWidgetInspectorOverride, isTrue); expect(WidgetsApp.debugShowWidgetInspectorOverride, isTrue);
expect(extensionChangedEvents.length, equals(1)); expect(extensionChangedEvents.length, equals(1));
expect(service.rebuildCount, equals(0)); // Should not be force rebuilt.
expect(debugShowChangeCounter, equals(1));
expect( expect(
await service.testBoolExtension( await service.testBoolExtension(
WidgetInspectorServiceExtensions.show.name, WidgetInspectorServiceExtensions.show.name,
...@@ -4150,7 +4175,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4150,7 +4175,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
extensionChangedEvent = extensionChangedEvents.last; extensionChangedEvent = extensionChangedEvents.last;
expect(extensionChangedEvent['extension'], equals('ext.flutter.inspector.show')); expect(extensionChangedEvent['extension'], equals('ext.flutter.inspector.show'));
expect(extensionChangedEvent['value'], isTrue); expect(extensionChangedEvent['value'], isTrue);
expect(service.rebuildCount, equals(1)); expect(service.rebuildCount, equals(0)); // Should not be force rebuilt.
expect(debugShowChangeCounter, equals(1));
expect( expect(
await service.testBoolExtension( await service.testBoolExtension(
WidgetInspectorServiceExtensions.show.name, WidgetInspectorServiceExtensions.show.name,
...@@ -4162,6 +4188,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4162,6 +4188,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
extensionChangedEvent = extensionChangedEvents.last; extensionChangedEvent = extensionChangedEvents.last;
expect(extensionChangedEvent['extension'], equals('ext.flutter.inspector.show')); expect(extensionChangedEvent['extension'], equals('ext.flutter.inspector.show'));
expect(extensionChangedEvent['value'], isFalse); expect(extensionChangedEvent['value'], isFalse);
expect(service.rebuildCount, equals(0)); // Should not be force rebuilt.
expect(debugShowChangeCounter, equals(2));
expect( expect(
await service.testBoolExtension( await service.testBoolExtension(
WidgetInspectorServiceExtensions.show.name, WidgetInspectorServiceExtensions.show.name,
...@@ -4170,7 +4198,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4170,7 +4198,8 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
equals('false'), equals('false'),
); );
expect(extensionChangedEvents.length, equals(3)); expect(extensionChangedEvents.length, equals(3));
expect(service.rebuildCount, equals(2)); expect(service.rebuildCount, equals(0)); // Should not be force rebuilt.
expect(debugShowChangeCounter, equals(2));
expect(WidgetsApp.debugShowWidgetInspectorOverride, isFalse); expect(WidgetsApp.debugShowWidgetInspectorOverride, isFalse);
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment