Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
bf6fcee1
Unverified
Commit
bf6fcee1
authored
Mar 09, 2022
by
LongCatIsLooong
Committed by
GitHub
Mar 09, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Avoid calling `performLayout` when only the relayout boundary is different (#99056)
parent
5f76ac35
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
96 additions
and
9 deletions
+96
-9
object.dart
packages/flutter/lib/src/rendering/object.dart
+35
-9
relayout_boundary_test.dart
packages/flutter/test/rendering/relayout_boundary_test.dart
+61
-0
No files found.
packages/flutter/lib/src/rendering/object.dart
View file @
bf6fcee1
...
@@ -1629,7 +1629,16 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
...
@@ -1629,7 +1629,16 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
assert
(
_debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout
());
assert
(
_debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout
());
return
;
return
;
}
}
assert
(
_relayoutBoundary
!=
null
);
if
(
_relayoutBoundary
==
null
)
{
_needsLayout
=
true
;
if
(
parent
!=
null
)
{
// _relayoutBoundary is cleaned by an ancestor in RenderObject.layout.
// Conservatively mark everything dirty until it reaches the closest
// known relayout boundary.
markParentNeedsLayout
();
}
return
;
}
if
(
_relayoutBoundary
!=
this
)
{
if
(
_relayoutBoundary
!=
this
)
{
markParentNeedsLayout
();
markParentNeedsLayout
();
}
else
{
}
else
{
...
@@ -1683,16 +1692,31 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
...
@@ -1683,16 +1692,31 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
void
_cleanRelayoutBoundary
()
{
void
_cleanRelayoutBoundary
()
{
if
(
_relayoutBoundary
!=
this
)
{
if
(
_relayoutBoundary
!=
this
)
{
_relayoutBoundary
=
null
;
_relayoutBoundary
=
null
;
_needsLayout
=
true
;
visitChildren
(
_cleanChildRelayoutBoundary
);
visitChildren
(
_cleanChildRelayoutBoundary
);
}
}
}
}
void
_propagateRelayoutBoundary
()
{
if
(
_relayoutBoundary
==
this
)
{
return
;
}
final
RenderObject
?
parentRelayoutBoundary
=
(
parent
as
RenderObject
?)?.
_relayoutBoundary
;
assert
(
parentRelayoutBoundary
!=
null
);
if
(
parentRelayoutBoundary
!=
_relayoutBoundary
)
{
_relayoutBoundary
=
parentRelayoutBoundary
;
visitChildren
(
_propagateRelayoutBoundaryToChild
);
}
}
// Reduces closure allocation for visitChildren use cases.
// Reduces closure allocation for visitChildren use cases.
static
void
_cleanChildRelayoutBoundary
(
RenderObject
child
)
{
static
void
_cleanChildRelayoutBoundary
(
RenderObject
child
)
{
child
.
_cleanRelayoutBoundary
();
child
.
_cleanRelayoutBoundary
();
}
}
static
void
_propagateRelayoutBoundaryToChild
(
RenderObject
child
)
{
child
.
_propagateRelayoutBoundary
();
}
/// Bootstrap the rendering pipeline by scheduling the very first layout.
/// Bootstrap the rendering pipeline by scheduling the very first layout.
///
///
/// Requires this render object to be attached and that this render object
/// Requires this render object to be attached and that this render object
...
@@ -1814,17 +1838,14 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
...
@@ -1814,17 +1838,14 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
));
));
assert
(!
_debugDoingThisResize
);
assert
(!
_debugDoingThisResize
);
assert
(!
_debugDoingThisLayout
);
assert
(!
_debugDoingThisLayout
);
RenderObject
?
relayoutBoundary
;
final
bool
isRelayoutBoundary
=
!
parentUsesSize
||
sizedByParent
||
constraints
.
isTight
||
parent
is
!
RenderObject
;
if
(!
parentUsesSize
||
sizedByParent
||
constraints
.
isTight
||
parent
is
!
RenderObject
)
{
final
RenderObject
relayoutBoundary
=
isRelayoutBoundary
?
this
:
(
parent
!
as
RenderObject
).
_relayoutBoundary
!;
relayoutBoundary
=
this
;
}
else
{
relayoutBoundary
=
(
parent
!
as
RenderObject
).
_relayoutBoundary
;
}
assert
(()
{
assert
(()
{
_debugCanParentUseSize
=
parentUsesSize
;
_debugCanParentUseSize
=
parentUsesSize
;
return
true
;
return
true
;
}());
}());
if
(!
_needsLayout
&&
constraints
==
_constraints
&&
relayoutBoundary
==
_relayoutBoundary
)
{
if
(!
_needsLayout
&&
constraints
==
_constraints
)
{
assert
(()
{
assert
(()
{
// in case parentUsesSize changed since the last invocation, set size
// in case parentUsesSize changed since the last invocation, set size
// to itself, so it has the right internal debug values.
// to itself, so it has the right internal debug values.
...
@@ -1839,6 +1860,11 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
...
@@ -1839,6 +1860,11 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
return
true
;
return
true
;
}());
}());
if
(
relayoutBoundary
!=
_relayoutBoundary
)
{
_relayoutBoundary
=
relayoutBoundary
;
visitChildren
(
_propagateRelayoutBoundaryToChild
);
}
if
(!
kReleaseMode
&&
debugProfileLayoutsEnabled
)
if
(!
kReleaseMode
&&
debugProfileLayoutsEnabled
)
Timeline
.
finishSync
();
Timeline
.
finishSync
();
return
;
return
;
...
...
packages/flutter/test/rendering/relayout_boundary_test.dart
0 → 100644
View file @
bf6fcee1
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'relayout boundary change does not trigger relayout'
,
(
WidgetTester
tester
)
async
{
final
RenderLayoutCount
renderLayoutCount
=
RenderLayoutCount
();
final
Widget
layoutCounter
=
Center
(
key:
GlobalKey
(),
child:
WidgetToRenderBoxAdapter
(
renderBox:
renderLayoutCount
),
);
await
tester
.
pumpWidget
(
Center
(
child:
SizedBox
(
width:
100
,
height:
100
,
child:
Center
(
child:
SizedBox
(
width:
100
,
height:
100
,
child:
Center
(
child:
layoutCounter
,
),
),
),
),
),
);
expect
(
renderLayoutCount
.
layoutCount
,
1
);
await
tester
.
pumpWidget
(
Center
(
child:
SizedBox
(
width:
100
,
height:
100
,
child:
layoutCounter
,
),
),
);
expect
(
renderLayoutCount
.
layoutCount
,
1
);
});
}
// This class is needed because LayoutBuilder's RenderObject does not always
// call the builder method in its PerformLayout method.
class
RenderLayoutCount
extends
RenderBox
{
int
layoutCount
=
0
;
@override
void
performLayout
()
{
layoutCount
+=
1
;
size
=
constraints
.
biggest
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment