Repository navigation
LayoutBuilder's descendant widgets should not rebuild more than once in the same frame #146379
Copy link
Copy link
Closed
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: tests"flutter test", flutter_test, or one of our tests"flutter test", flutter_test, or one of our testsfound 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.22frameworkflutter/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 onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
testWidgets('LayoutBuilder rebuids twice', (WidgetTester tester) async {
int built = 0;
final target = LayoutBuilder(
builder: (context, constraints) {
return Builder(builder: (context) {
built += 1;
MediaQuery.of(context);
return const Placeholder();
});
},
);
expect(built, 0);
await tester.pumpWidget(MediaQuery(
data: const MediaQueryData(size: Size(400.0, 300.0)),
child: Center(
child: SizedBox(
width: 400.0,
child: target,
),
),
));
expect(built, 1);
await tester.pumpWidget(MediaQuery(
data: const MediaQueryData(size: Size(300.0, 400.0)),
child: Center(
child: SizedBox(
width: 300.0,
child: target,
),
),
));
expect(built, 2);
});The following TestFailure was thrown running a test:
Expected: <2>
Actual: <3>
This came up again in #143249: we can't use a LayoutBuilder to 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 LayoutBuilder boundary:
ControllerOwner -> LayoutBuilder -> IntermediateWidget -> ControllerUser.
If ControllerUser rebulids without IntermediateWidget rebuilding (as seen in the test), it may keep using an outdated / disposed controller.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: tests"flutter test", flutter_test, or one of our tests"flutter test", flutter_test, or one of our testsfound 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.22frameworkflutter/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 onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Activity
darshankawar commentedon Apr 8, 2024
I was able to replicate this using the test code provided.
stable, master flutter doctor -v
[-]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[/+]LongCatIsLooong commentedon Apr 30, 2024
Another case of this issue:
The framework would incorrectly report that there were duplicate global keys:
because the
widgetWithKeybuilder will run twice during the secondpumpWidget.chunhtai commentedon Apr 30, 2024
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?
LongCatIsLooong commentedon May 1, 2024
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:while the correct tree looks like this:
The LayoutBuilder stole the keyed SizedBox during the first build, and the SizedBox was then unmounted.
Prevent LayoutBuilder from rebuilding more than once (#147856)
Reverts "Prevent LayoutBuilder from rebuilding more than once (#147856)…
loic-sharma commentedon May 30, 2024
@LongCatIsLooong, I'm reopening this as the fix was reverted: #149279
Prevent LayoutBuilder from rebuilding more than once (flutter#147856)
Reverts "Prevent LayoutBuilder from rebuilding more than once (flutte…
gnprice commentedon Jun 7, 2024
FTR, the reland appears to be #149303.
github-actions commentedon Jun 21, 2024
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.