@@ -25,11 +25,18 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
2525 final String ? debugName;
2626 final bool debugShowZIndex;
2727
28- /// Using preprocessed constraints can improve performance, especially when
29- /// the ListView is swiping quickly, constraints are no longer calculated during
30- /// layout. Need to be used in conjunction with childConstraints.
31- final ProcessedChildConstraints ? processedChildConstraints;
32- final bool preprocessChildConstraints;
28+ ///By default, constraints are not recalculated during layout if the constraints of
29+ ///child elements do not change. Even the constraint computation is extremely fast.
30+ //
31+ // But when the ListView is swiped quickly, constraints are calculated for each item
32+ // layout process, even though the constraints of these items may not change. This is
33+ // not necessary. At this point ChildConstraintsCache can be used to optimize it so that
34+ // constraints for entries of the same type are computed only once. Refer to example/complex_list.dart
35+ //
36+ // Constraints can also be calculated ahead of time so that they don't need to be
37+ // calculated during layout. Refer to example/preprocess_complex_list.dart
38+ final ChildConstraintsCache ? childConstraintsCache;
39+ final bool useCacheConstraints;
3340
3441 ConstraintLayout ({
3542 Key ? key,
@@ -43,8 +50,8 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
4350 this .releasePrintLayoutTime = false ,
4451 this .debugName,
4552 this .debugShowZIndex = false ,
46- this .preprocessChildConstraints = false ,
47- this .processedChildConstraints ,
53+ this .useCacheConstraints = false ,
54+ this .childConstraintsCache ,
4855 }) : super (
4956 key: key,
5057 children: children,
@@ -53,8 +60,7 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
5360 @override
5461 RenderObject createRenderObject (BuildContext context) {
5562 assert (_debugEnsureNotEmptyString ('debugName' , debugName));
56- assert (preprocessChildConstraints == false ||
57- (processedChildConstraints != null ));
63+ assert (useCacheConstraints == false || (childConstraintsCache != null ));
5864 return _ConstraintRenderBox ()
5965 .._childConstraints = childConstraints
6066 .._debugShowGuideline = debugShowGuideline
@@ -65,8 +71,8 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
6571 .._releasePrintLayoutTime = releasePrintLayoutTime
6672 .._debugName = debugName
6773 .._debugShowZIndex = debugShowZIndex
68- .._preprocessChildConstraints = preprocessChildConstraints
69- .._processedChildConstraints = processedChildConstraints ;
74+ .._useCacheConstraints = useCacheConstraints
75+ .._childConstraintsCache = childConstraintsCache ;
7076 }
7177
7278 @override
@@ -75,6 +81,7 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
7581 covariant RenderObject renderObject,
7682 ) {
7783 assert (_debugEnsureNotEmptyString ('debugName' , debugName));
84+ assert (useCacheConstraints == false || (childConstraintsCache != null ));
7885 (renderObject as _ConstraintRenderBox )
7986 ..childConstraints = childConstraints
8087 ..debugShowGuideline = debugShowGuideline
@@ -85,21 +92,20 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
8592 ..releasePrintLayoutTime = releasePrintLayoutTime
8693 ..debugName = debugName
8794 ..debugShowZIndex = debugShowZIndex
88- ..preprocessChildConstraints = preprocessChildConstraints
89- ..processedChildConstraints = processedChildConstraints ;
95+ ..useCacheConstraints = useCacheConstraints
96+ ..childConstraintsCache = childConstraintsCache ;
9097 }
9198
92- static ProcessedChildConstraints preprocess (
99+ static ChildConstraintsCache generateCache (
93100 List <Constraint > childConstraints) {
94- ProcessedChildConstraints processedChildConstraints =
95- ProcessedChildConstraints ();
101+ ChildConstraintsCache processedChildConstraints = ChildConstraintsCache ();
96102 processedChildConstraints._processedNodesMap = {};
97103
98104 _ConstrainedNode _getConstrainedNodeForChild (
99105 RenderBox ? child,
100106 ConstraintId id,
101107 ) {
102- return processedChildConstraints._processedNodesMap
108+ return processedChildConstraints._processedNodesMap!
103109 .putIfAbsent (id, () => _ConstrainedNode ()..nodeId = id);
104110 }
105111
@@ -237,13 +243,13 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
237243 currentNode.baselineAlignType = constraint.baseline! .type;
238244 }
239245
240- processedChildConstraints._processedNodesMap[constraint.id! ] =
246+ processedChildConstraints._processedNodesMap! [constraint.id! ] =
241247 currentNode;
242248 }
243249
244- processedChildConstraints._processedNodesMap.remove (parent);
250+ processedChildConstraints._processedNodesMap! .remove (parent);
245251 processedChildConstraints._processedNodes =
246- processedChildConstraints._processedNodesMap.values.toList ();
252+ processedChildConstraints._processedNodesMap! .values.toList ();
247253
248254 return processedChildConstraints;
249255 }
@@ -1341,12 +1347,11 @@ class _ConstraintRenderBox extends RenderBox
13411347 late bool _releasePrintLayoutTime;
13421348 String ? _debugName;
13431349 late bool _debugShowZIndex;
1344- late bool _preprocessChildConstraints ;
1345- ProcessedChildConstraints ? _processedChildConstraints ;
1350+ late bool _useCacheConstraints ;
1351+ ChildConstraintsCache ? _childConstraintsCache ;
13461352
13471353 bool _needsRecalculateConstraints = true ;
13481354 bool _needsReorderChildren = true ;
1349- final Map <RenderBox , _ConstrainedNode > _tempConstrainedNodeMap = HashMap ();
13501355 final Map <ConstraintId , _ConstrainedNode > _constrainedNodeMap = HashMap ();
13511356
13521357 /// For layout
@@ -1450,17 +1455,21 @@ class _ConstraintRenderBox extends RenderBox
14501455 }
14511456 }
14521457
1453- set preprocessChildConstraints (bool value) {
1454- if (_preprocessChildConstraints != value) {
1455- _preprocessChildConstraints = value;
1458+ set useCacheConstraints (bool value) {
1459+ if (_useCacheConstraints != value) {
1460+ _useCacheConstraints = value;
1461+ if (! value && _childConstraintsCache != null ) {
1462+ _childConstraintsCache! ._processedNodes = null ;
1463+ _childConstraintsCache! ._processedNodesMap = null ;
1464+ }
14561465 markNeedsRecalculateConstraints ();
14571466 markNeedsLayout ();
14581467 }
14591468 }
14601469
1461- set processedChildConstraints ( ProcessedChildConstraints ? value) {
1462- if (_processedChildConstraints != value) {
1463- _processedChildConstraints = value;
1470+ set childConstraintsCache ( ChildConstraintsCache ? value) {
1471+ if (_childConstraintsCache != value) {
1472+ _childConstraintsCache = value;
14641473 markNeedsRecalculateConstraints ();
14651474 markNeedsLayout ();
14661475 }
@@ -1632,17 +1641,18 @@ class _ConstraintRenderBox extends RenderBox
16321641 id, () => _ConstrainedNode ()..nodeId = id);
16331642 if (child != null && node.renderBox == null ) {
16341643 node.renderBox = child;
1635- _tempConstrainedNodeMap[child] = node;
16361644 }
16371645 return node;
16381646 }
16391647
16401648 void _buildConstrainedNodeTrees () {
1641- _tempConstrainedNodeMap.clear ();
16421649 _constrainedNodeMap.clear ();
1650+ if (_useCacheConstraints) {
1651+ _childConstraintsCache! ._processedNodes = [];
1652+ }
1653+
16431654 RenderBox ? child = firstChild;
16441655 int childIndex = - 1 ;
1645-
16461656 while (child != null ) {
16471657 childIndex++ ;
16481658 _ConstraintBoxData childParentData =
@@ -1687,8 +1697,17 @@ class _ConstraintRenderBox extends RenderBox
16871697 currentNode.baselineAlignType = childParentData.baseline! .type;
16881698 }
16891699
1700+ if (_useCacheConstraints) {
1701+ _childConstraintsCache! ._processedNodes! .add (currentNode);
1702+ }
1703+
16901704 child = childParentData.nextSibling;
16911705 }
1706+
1707+ _constrainedNodeMap.remove (parent);
1708+ if (_useCacheConstraints) {
1709+ _childConstraintsCache! ._processedNodesMap = _constrainedNodeMap;
1710+ }
16921711 }
16931712
16941713 @override
@@ -1741,10 +1760,11 @@ class _ConstraintRenderBox extends RenderBox
17411760 return true ;
17421761 }());
17431762
1744- if (_preprocessChildConstraints) {
1763+ if (_useCacheConstraints &&
1764+ _childConstraintsCache! ._processedNodes != null ) {
17451765 List <_ConstrainedNode > layoutList = [];
17461766 List <_ConstrainedNode > paintList = [];
1747- for (final element in _processedChildConstraints ! ._processedNodes) {
1767+ for (final element in _childConstraintsCache ! ._processedNodes! ) {
17481768 _ConstrainedNode constrainedNode = _ConstrainedNode ()
17491769 ..nodeId = element.nodeId
17501770 ..leftConstraint = element.leftConstraint
@@ -1769,7 +1789,7 @@ class _ConstraintRenderBox extends RenderBox
17691789 _ConstraintBoxData childParentData =
17701790 child.parentData as _ConstraintBoxData ;
17711791 childParentData._constrainedNodeMap =
1772- _processedChildConstraints ! ._processedNodesMap;
1792+ _childConstraintsCache ! ._processedNodesMap! ;
17731793 _layoutOrderList[childIndex].parentData = childParentData;
17741794 _layoutOrderList[childIndex].index = childIndex;
17751795 _layoutOrderList[childIndex].renderBox = child;
@@ -1807,7 +1827,7 @@ class _ConstraintRenderBox extends RenderBox
18071827 _ConstraintBoxData childParentData =
18081828 child.parentData as _ConstraintBoxData ;
18091829 childParentData._constrainedNodeMap =
1810- _processedChildConstraints ! ._processedNodesMap;
1830+ _childConstraintsCache ! ._processedNodesMap! ;
18111831 _paintingOrderList[childIndex].parentData = childParentData;
18121832 _paintingOrderList[childIndex].index = childIndex;
18131833 _paintingOrderList[childIndex].renderBox = child;
@@ -1831,17 +1851,16 @@ class _ConstraintRenderBox extends RenderBox
18311851 assert (() {
18321852 if (_debugCheckConstraints) {
18331853 List <_ConstrainedNode > nodeList =
1834- _tempConstrainedNodeMap .values.toList ();
1854+ _constrainedNodeMap .values.toList ();
18351855 _debugCheckConstraintsIntegrity (nodeList);
18361856 _debugCheckLoopConstraints (nodeList);
18371857 }
18381858 return true ;
18391859 }());
18401860
18411861 /// Sort by the depth of constraint from shallow to deep, the lowest depth is 0, representing parent
1842- _layoutOrderList = _tempConstrainedNodeMap.values.toList ();
1843- _paintingOrderList = _tempConstrainedNodeMap.values.toList ();
1844- _tempConstrainedNodeMap.clear ();
1862+ _layoutOrderList = _constrainedNodeMap.values.toList ();
1863+ _paintingOrderList = _constrainedNodeMap.values.toList ();
18451864
18461865 _layoutOrderList.sort ((left, right) {
18471866 return left.getDepth () - right.getDepth ();
@@ -2658,9 +2677,9 @@ class _ConstraintRenderBox extends RenderBox
26582677 }
26592678}
26602679
2661- class ProcessedChildConstraints {
2662- late List <_ConstrainedNode > _processedNodes;
2663- late Map <ConstraintId , _ConstrainedNode > _processedNodesMap;
2680+ class ChildConstraintsCache {
2681+ List <_ConstrainedNode >? _processedNodes;
2682+ Map <ConstraintId , _ConstrainedNode >? _processedNodesMap;
26642683}
26652684
26662685class _ConstrainedNode {
0 commit comments