Repository navigation
LayoutBuilder's descendant widgets should not rebuild more than once in the same frame #146379
Description
Activity
- addedin triagePresently being triaged by the triage teamPresently being triaged by the triage team
on Apr 8, 2024 I was able to replicate this using the test code provided.
stable, master flutter doctor -v
[!] Flutter (Channel stable, 3.19.5, on macOS 12.2.1 21D62 darwin-x64, locale en-GB) • Flutter version 3.19.5 on channel stable at /Users/dhs/documents/fluttersdk/flutter ! Warning: `flutter` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision 300451adae (4 days ago), 2024-03-27 21:54:07 -0500 • Engine revision e76c956498 • Dart version 3.3.3 • DevTools version 2.31.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [!] Xcode - develop for iOS and macOS (Xcode 12.3) • Xcode at /Applications/Xcode.app/Contents/Developer ! Flutter recommends a minimum Xcode version of 13. Download the latest version or update via the Mac App Store. • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (5 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 11 (API 30) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category. [!] Flutter (Channel master, 3.22.0-5.0.pre.55, on macOS 12.2.1 21D62 darwin-x64, locale en-GB) • Flutter version 3.22.0-5.0.pre.55 on channel master at /Users/dhs/documents/fluttersdk/flutter ! Warning: `flutter` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision ddf79b755d (6 hours ago), 2024-04-07 18:34:24 -0400 • Engine revision c10e950c66 • Dart version 3.5.0 (build 3.5.0-18.0.dev) • DevTools version 2.34.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [!] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Users/dhs/Library/Android/sdk ✗ cmdline-tools component is missing Run `path/to/sdkmanager --install "cmdline-tools;latest"` See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 13C100 • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] IntelliJ IDEA Ultimate Edition (version 2021.3.2) • IntelliJ at /Applications/IntelliJ IDEA.app • Flutter plugin version 65.1.4 • Dart plugin version 213.7228 [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.29.0 [✓] Connected device (3 available) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 15.3.1 19D52 • macOS (desktop) • macos • darwin-x64 • macOS 12.2.1 21D62 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. [!] Xcode - develop for iOS and macOS (Xcode 12.3) • Xcode at /Applications/Xcode.app/Contents/Developer ! Flutter recommends a minimum Xcode version of 13. Download the latest version or update via the Mac App Store. • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (5 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 11 (API 30) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category.- addeda: tests"flutter test", flutter_test, or one of our tests"flutter test", flutter_test, or one of our testsframeworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onteam-frameworkOwned by Framework teamOwned by Framework teamfound in release: 3.19Found to occur in 3.19Found to occur in 3.19found in release: 3.22Found to occur in 3.22Found to occur in 3.22and removedin triagePresently being triaged by the triage teamPresently being triaged by the triage team
on Apr 8, 2024 - addedP2Important issues not at the top of the work listImportant issues not at the top of the work listtriaged-frameworkTriaged by Framework teamTriaged by Framework team
on Apr 9, 2024 - changed the title
[-]LayoutBuilder's descentant widgets should not rebulid more than once in the same frame[/-][+]LayoutBuilder's descendant widgets should not rebuild more than once in the same frame[/+]on Apr 10, 2024 LongCatIsLooong commented
on Apr 30, 2024 ContributorAuthorMore actionsAnother case of this issue:
testWidgets('duplicate GlobalKey false positive', (WidgetTester tester) async { final widgetKey = GlobalKey(debugLabel: 'widget key'); final widgetWithKey = Builder(builder: (context) { Directionality.of(context); return SizedBox(key: widgetKey); }); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Row( children: [ LayoutBuilder( builder: (context, constraints) => widgetWithKey, ), ], ), ), ); await tester.pumpWidget( Directionality( textDirection: TextDirection.rtl, child: Row( children: [ LayoutBuilder( builder: (context, constraints) => const Placeholder(), ), widgetWithKey, ], ), ), ); });
The framework would incorrectly report that there were duplicate global keys:
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in widget tree.because the
widgetWithKeybuilder will run twice during the secondpumpWidget.I tried to handle cases where layoutbuilders are involved https://docs.google.com/document/d/15U1XDLrP-SXfgeu5DBBsA7MQuFpDUW005Y2ObwmYWIc/edit#heading=h.pub7jnop54q0
looks like i missed some use cases?
I tried to handle cases where layoutbuilders are involved https://docs.google.com/document/d/15U1XDLrP-SXfgeu5DBBsA7MQuFpDUW005Y2ObwmYWIc/edit#heading=h.pub7jnop54q0
looks like i missed some use cases?
I think in this case it's actually worse than an incorrect assert. The final widget tree is incorrect with the
LayoutBuilderdouble rebuild. The example from #146379 (comment) generates the following widget tree:└Directionality(textDirection: rtl) └Row(direction: horizontal, mainAxisAlignment: start, crossAxisAlignment: center, dependencies: [Directionality], renderObject: RenderFlex#860c2) ├LayoutBuilder(renderObject: _RenderLayoutBuilder#d1a04 relayoutBoundary=up1) │└Placeholder │ └LimitedBox(maxWidth: 400.0, maxHeight: 400.0, renderObject: RenderLimitedBox#2a215 relayoutBoundary=up2) │ └CustomPaint(renderObject: RenderCustomPaint#d44b0 relayoutBoundary=up3) └Builder(dependencies: [Directionality])while the correct tree looks like this:
└Directionality(textDirection: rtl) └Row(direction: horizontal, mainAxisAlignment: start, crossAxisAlignment: center, dependencies: [Directionality], renderObject: RenderFlex#0fc0c) ├LayoutBuilder(renderObject: _RenderLayoutBuilder#ac777 relayoutBoundary=up1) │└Placeholder │ └LimitedBox(maxWidth: 400.0, maxHeight: 400.0, renderObject: RenderLimitedBox#aca20 relayoutBoundary=up2) │ └CustomPaint(renderObject: RenderCustomPaint#09849 relayoutBoundary=up3) └Builder(dependencies: [Directionality]) └SizedBox-[GlobalKey#0d1ba widget key](renderObject: RenderConstrainedBox#996dc relayoutBoundary=up1)The LayoutBuilder stole the keyed SizedBox during the first build, and the SizedBox was then unmounted.
Reacted by chunhtai@LongCatIsLooong, I'm reopening this as the fix was reverted: #149279
Reacted by LongCatIsLooong- addedr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer version
on Jun 7, 2024 FTR, the reland appears to be #149303.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.- locked as resolved and limited conversation to collaborators
on Jun 21, 2024
This came up again in #143249: we can't use a
LayoutBuilderto get the incoming constraints because a google internal test failure caused by this.This becomes problematic when a disposable object (such as a controller) is passed down the widget tree as a widget parameter, across the
LayoutBuilderboundary:ControllerOwner -> LayoutBuilder -> IntermediateWidget -> ControllerUser.
If ControllerUser rebulids without IntermediateWidget rebuilding (as seen in the test), it may keep using an outdated / disposed controller.