Show debug-mode message for widget rebuilds in profile mode (#9755)
When running in profile mode, the Performance panel showed a
disabled 'Count widget builds' checkbox which was misleading.
Widget rebuild counts rely on debugOnRebuildDirtyWidget which
is only available in debug mode.
This change:
- Removes the checkbox when running in profile mode
- Shows a clear message: 'Rebuild information is not available
for this frame. Widget rebuild counts are only available when
running an app in debug-mode.'
- Adds widget tests for both profile mode and debug mode behavior
Fixes #9730
---------
Co-authored-by: Sam Rawlins <srawlins@google.com>
diff --git a/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart b/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart
index a19d250..6b7ec33 100644
--- a/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart
+++ b/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart
@@ -20,6 +20,12 @@
import '../flutter_frames/flutter_frame_model.dart';
import 'rebuild_stats_model.dart';
+@visibleForTesting
+const debugModeOnlyMessage =
+ 'Rebuild information is not available for this frame.\n'
+ 'Widget rebuild counts are only available when running '
+ 'an app in debug mode.';
+
class RebuildStatsView extends StatefulWidget {
const RebuildStatsView({
super.key,
@@ -92,6 +98,12 @@
@override
Widget build(BuildContext context) {
+ final isProfileBuild =
+ serviceConnection.serviceManager.connectedApp?.isProfileBuildNow ??
+ false;
+ if (isProfileBuild) {
+ return const CenteredMessage(message: debugModeOnlyMessage);
+ }
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
index 1e4cda3..10b1377 100644
--- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
+++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -31,6 +31,9 @@
* Fixed a bug where the Flutter frames chart could appear frozen after
switching away from the Performance screen and coming back.
[#9960](https://github.com/flutter/devtools/pull/9960)
+* Added a message in the Performance panel when widget rebuild tracking is
+ unavailable because the app is running in profile mode.
+ [#9755](https://github.com/flutter/devtools/pull/9755)
## CPU profiler updates
@@ -40,15 +43,16 @@
## Memory updates
-* Added the ability to pin classes to the top of the Profile Memory table. [#8898](https://github.com/flutter/devtools/issues/8898)
+* Added the ability to pin classes to the top of the Profile Memory table.
+ [#8898](https://github.com/flutter/devtools/issues/8898)
## Debugger updates
-* Prevent values from being garbage-collected, while being evaluated.
+* Prevented values from being garbage-collected, while being evaluated.
[#9885](https://github.com/flutter/devtools/pull/9885)
* Update to latest version of the Dart syntax highlighting grammar
[#9920](https://github.com/flutter/devtools/pull/9920).
-* Fix a bug in the TextMate grammar parser that could result in code after
+* Fixed a bug in the TextMate grammar parser that could result in code after
comments being classified as comments.
[#9921](https://github.com/flutter/devtools/pull/9921).
* Fixed an overflow in the debugging controls when the Debugger screen is
@@ -70,7 +74,7 @@
## Logging updates
-* Correct time units and cumulative nature of GC events.
+* Corrected time units and cumulative nature of GC events.
[#9890](https://github.com/flutter/devtools/pull/9890)
* Fixed a bug where long `dart:developer` log messages lost their structured
Details view. -
@@ -83,7 +87,7 @@
## Deep links tool updates
* Added a "Watch tutorial" link to the status line that points to the
- [deep links video tutorial](https://youtu.be/d7sZL6h1Elw).
+ [deep links video tutorial](https://youtu.be/d7sZL6hIElw).
[#9925](https://github.com/flutter/devtools/pull/9925)
## VS Code sidebar updates
@@ -92,12 +96,13 @@
## DevTools extension updates
-* Hide the DevTools extensions menu button in single-screen embedded mode (`EmbedMode.embedOne`) on standard screens.
+* Hide the DevTools extensions menu button in single-screen embedded mode
+ (`EmbedMode.embedOne`) on standard screens.
[#8507](https://github.com/flutter/devtools/issues/8507)
* Added iframe sandboxing for embedded DevTools extensions to enforce origin
isolation. [#9967](https://github.com/flutter/devtools/pull/9967)
-* Improved DevTools extension isolation by tracking the providing package name for
- enablement, deduplication, and asset loading.
+* Improved DevTools extension isolation by tracking the providing package
+ name for enablement, deduplication, and asset loading.
[#9981](https://github.com/flutter/devtools/pull/9981)
## Advanced developer mode updates
@@ -107,4 +112,4 @@
## Full commit history
To find a complete list of changes in this release, check out the
-[DevTools git log](https://github.com/flutter/devtools/tree/v2.61.0).
+[DevTools git log](https://github.com/flutter/devtools/tree/v2.61.0).
\ No newline at end of file
diff --git a/packages/devtools_app/test/screens/performance/performance_screen_test.dart b/packages/devtools_app/test/screens/performance/performance_screen_test.dart
index 6f23218..8d24ef2 100644
--- a/packages/devtools_app/test/screens/performance/performance_screen_test.dart
+++ b/packages/devtools_app/test/screens/performance/performance_screen_test.dart
@@ -9,6 +9,7 @@
import 'package:devtools_app/devtools_app.dart';
import 'package:devtools_app/src/screens/performance/panes/controls/performance_controls.dart';
+import 'package:devtools_app/src/screens/performance/panes/rebuild_stats/rebuild_stats.dart';
import 'package:devtools_app/src/screens/performance/panes/timeline_events/timeline_events_view.dart';
import 'package:devtools_app/src/screens/performance/tabbed_performance_view.dart';
import 'package:devtools_app/src/shared/feature_flags.dart';
@@ -218,7 +219,6 @@
await tester.runAsync(() async {
await pumpPerformanceScreen(tester, runAsync: true);
await tester.pumpAndSettle();
-
final chartButtonFinder = find.byType(VisibilityButton);
expect(chartButtonFinder, findsOneWidget);
@@ -231,7 +231,6 @@
await tester.tap(chartButtonFinder);
await tester.pumpAndSettle();
-
// The flutter frames chart should no longer be visible.
expect(find.byType(FramesChartControls), findsNothing);
expect(
@@ -395,6 +394,64 @@
},
);
});
+
+ group('RebuildStatsView', () {
+ late FakeServiceConnectionManager fakeServiceConnection;
+ late RebuildCountModel model;
+ late ValueNotifier<FlutterFrame?> selectedFrame;
+
+ setUp(() {
+ fakeServiceConnection = FakeServiceConnectionManager();
+ mockConnectedApp(fakeServiceConnection.serviceManager.connectedApp!);
+ setGlobal(ServiceConnectionManager, fakeServiceConnection);
+ setGlobal(IdeTheme, IdeTheme());
+ setGlobal(NotificationService, NotificationService());
+ setGlobal(BannerMessagesController, BannerMessagesController());
+ setGlobal(PreferencesController, PreferencesController());
+ setGlobal(OfflineDataController, OfflineDataController());
+ model = RebuildCountModel();
+ selectedFrame = ValueNotifier<FlutterFrame?>(null);
+ });
+
+ testWidgets('shows message when running in profile mode', (
+ WidgetTester tester,
+ ) async {
+ mockConnectedApp(
+ fakeServiceConnection.serviceManager.connectedApp!,
+ isProfileBuild: true,
+ );
+
+ await tester.pumpWidget(
+ wrapWithControllers(
+ RebuildStatsView(model: model, selectedFrame: selectedFrame),
+ ),
+ );
+ await tester.pump();
+
+ expect(
+ find.textContaining('Widget rebuild counts are only available'),
+ findsOneWidget,
+ );
+ });
+
+ testWidgets('shows normal UI when running in debug mode', (
+ WidgetTester tester,
+ ) async {
+ mockConnectedApp(fakeServiceConnection.serviceManager.connectedApp!);
+
+ await tester.pumpWidget(
+ wrapWithControllers(
+ RebuildStatsView(model: model, selectedFrame: selectedFrame),
+ ),
+ );
+ await tester.pump();
+
+ expect(
+ find.textContaining('Widget rebuild counts are only available'),
+ findsNothing,
+ );
+ });
+ });
});
}