@@ -25,11 +25,18 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
25
25
final String ? debugName;
26
26
final bool debugShowZIndex;
27
27
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;
33
40
34
41
ConstraintLayout ({
35
42
Key ? key,
@@ -43,8 +50,8 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
43
50
this .releasePrintLayoutTime = false ,
44
51
this .debugName,
45
52
this .debugShowZIndex = false ,
46
- this .preprocessChildConstraints = false ,
47
- this .processedChildConstraints ,
53
+ this .useCacheConstraints = false ,
54
+ this .childConstraintsCache ,
48
55
}) : super (
49
56
key: key,
50
57
children: children,
@@ -53,8 +60,7 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
53
60
@override
54
61
RenderObject createRenderObject (BuildContext context) {
55
62
assert (_debugEnsureNotEmptyString ('debugName' , debugName));
56
- assert (preprocessChildConstraints == false ||
57
- (processedChildConstraints != null ));
63
+ assert (useCacheConstraints == false || (childConstraintsCache != null ));
58
64
return _ConstraintRenderBox ()
59
65
.._childConstraints = childConstraints
60
66
.._debugShowGuideline = debugShowGuideline
@@ -65,8 +71,8 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
65
71
.._releasePrintLayoutTime = releasePrintLayoutTime
66
72
.._debugName = debugName
67
73
.._debugShowZIndex = debugShowZIndex
68
- .._preprocessChildConstraints = preprocessChildConstraints
69
- .._processedChildConstraints = processedChildConstraints ;
74
+ .._useCacheConstraints = useCacheConstraints
75
+ .._childConstraintsCache = childConstraintsCache ;
70
76
}
71
77
72
78
@override
@@ -75,6 +81,7 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
75
81
covariant RenderObject renderObject,
76
82
) {
77
83
assert (_debugEnsureNotEmptyString ('debugName' , debugName));
84
+ assert (useCacheConstraints == false || (childConstraintsCache != null ));
78
85
(renderObject as _ConstraintRenderBox )
79
86
..childConstraints = childConstraints
80
87
..debugShowGuideline = debugShowGuideline
@@ -85,21 +92,20 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
85
92
..releasePrintLayoutTime = releasePrintLayoutTime
86
93
..debugName = debugName
87
94
..debugShowZIndex = debugShowZIndex
88
- ..preprocessChildConstraints = preprocessChildConstraints
89
- ..processedChildConstraints = processedChildConstraints ;
95
+ ..useCacheConstraints = useCacheConstraints
96
+ ..childConstraintsCache = childConstraintsCache ;
90
97
}
91
98
92
- static ProcessedChildConstraints preprocess (
99
+ static ChildConstraintsCache generateCache (
93
100
List <Constraint > childConstraints) {
94
- ProcessedChildConstraints processedChildConstraints =
95
- ProcessedChildConstraints ();
101
+ ChildConstraintsCache processedChildConstraints = ChildConstraintsCache ();
96
102
processedChildConstraints._processedNodesMap = {};
97
103
98
104
_ConstrainedNode _getConstrainedNodeForChild (
99
105
RenderBox ? child,
100
106
ConstraintId id,
101
107
) {
102
- return processedChildConstraints._processedNodesMap
108
+ return processedChildConstraints._processedNodesMap!
103
109
.putIfAbsent (id, () => _ConstrainedNode ()..nodeId = id);
104
110
}
105
111
@@ -237,13 +243,13 @@ class ConstraintLayout extends MultiChildRenderObjectWidget {
237
243
currentNode.baselineAlignType = constraint.baseline! .type;
238
244
}
239
245
240
- processedChildConstraints._processedNodesMap[constraint.id! ] =
246
+ processedChildConstraints._processedNodesMap! [constraint.id! ] =
241
247
currentNode;
242
248
}
243
249
244
- processedChildConstraints._processedNodesMap.remove (parent);
250
+ processedChildConstraints._processedNodesMap! .remove (parent);
245
251
processedChildConstraints._processedNodes =
246
- processedChildConstraints._processedNodesMap.values.toList ();
252
+ processedChildConstraints._processedNodesMap! .values.toList ();
247
253
248
254
return processedChildConstraints;
249
255
}
@@ -1341,12 +1347,11 @@ class _ConstraintRenderBox extends RenderBox
1341
1347
late bool _releasePrintLayoutTime;
1342
1348
String ? _debugName;
1343
1349
late bool _debugShowZIndex;
1344
- late bool _preprocessChildConstraints ;
1345
- ProcessedChildConstraints ? _processedChildConstraints ;
1350
+ late bool _useCacheConstraints ;
1351
+ ChildConstraintsCache ? _childConstraintsCache ;
1346
1352
1347
1353
bool _needsRecalculateConstraints = true ;
1348
1354
bool _needsReorderChildren = true ;
1349
- final Map <RenderBox , _ConstrainedNode > _tempConstrainedNodeMap = HashMap ();
1350
1355
final Map <ConstraintId , _ConstrainedNode > _constrainedNodeMap = HashMap ();
1351
1356
1352
1357
/// For layout
@@ -1450,17 +1455,21 @@ class _ConstraintRenderBox extends RenderBox
1450
1455
}
1451
1456
}
1452
1457
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
+ }
1456
1465
markNeedsRecalculateConstraints ();
1457
1466
markNeedsLayout ();
1458
1467
}
1459
1468
}
1460
1469
1461
- set processedChildConstraints ( ProcessedChildConstraints ? value) {
1462
- if (_processedChildConstraints != value) {
1463
- _processedChildConstraints = value;
1470
+ set childConstraintsCache ( ChildConstraintsCache ? value) {
1471
+ if (_childConstraintsCache != value) {
1472
+ _childConstraintsCache = value;
1464
1473
markNeedsRecalculateConstraints ();
1465
1474
markNeedsLayout ();
1466
1475
}
@@ -1632,17 +1641,18 @@ class _ConstraintRenderBox extends RenderBox
1632
1641
id, () => _ConstrainedNode ()..nodeId = id);
1633
1642
if (child != null && node.renderBox == null ) {
1634
1643
node.renderBox = child;
1635
- _tempConstrainedNodeMap[child] = node;
1636
1644
}
1637
1645
return node;
1638
1646
}
1639
1647
1640
1648
void _buildConstrainedNodeTrees () {
1641
- _tempConstrainedNodeMap.clear ();
1642
1649
_constrainedNodeMap.clear ();
1650
+ if (_useCacheConstraints) {
1651
+ _childConstraintsCache! ._processedNodes = [];
1652
+ }
1653
+
1643
1654
RenderBox ? child = firstChild;
1644
1655
int childIndex = - 1 ;
1645
-
1646
1656
while (child != null ) {
1647
1657
childIndex++ ;
1648
1658
_ConstraintBoxData childParentData =
@@ -1687,8 +1697,17 @@ class _ConstraintRenderBox extends RenderBox
1687
1697
currentNode.baselineAlignType = childParentData.baseline! .type;
1688
1698
}
1689
1699
1700
+ if (_useCacheConstraints) {
1701
+ _childConstraintsCache! ._processedNodes! .add (currentNode);
1702
+ }
1703
+
1690
1704
child = childParentData.nextSibling;
1691
1705
}
1706
+
1707
+ _constrainedNodeMap.remove (parent);
1708
+ if (_useCacheConstraints) {
1709
+ _childConstraintsCache! ._processedNodesMap = _constrainedNodeMap;
1710
+ }
1692
1711
}
1693
1712
1694
1713
@override
@@ -1741,10 +1760,11 @@ class _ConstraintRenderBox extends RenderBox
1741
1760
return true ;
1742
1761
}());
1743
1762
1744
- if (_preprocessChildConstraints) {
1763
+ if (_useCacheConstraints &&
1764
+ _childConstraintsCache! ._processedNodes != null ) {
1745
1765
List <_ConstrainedNode > layoutList = [];
1746
1766
List <_ConstrainedNode > paintList = [];
1747
- for (final element in _processedChildConstraints ! ._processedNodes) {
1767
+ for (final element in _childConstraintsCache ! ._processedNodes! ) {
1748
1768
_ConstrainedNode constrainedNode = _ConstrainedNode ()
1749
1769
..nodeId = element.nodeId
1750
1770
..leftConstraint = element.leftConstraint
@@ -1769,7 +1789,7 @@ class _ConstraintRenderBox extends RenderBox
1769
1789
_ConstraintBoxData childParentData =
1770
1790
child.parentData as _ConstraintBoxData ;
1771
1791
childParentData._constrainedNodeMap =
1772
- _processedChildConstraints ! ._processedNodesMap;
1792
+ _childConstraintsCache ! ._processedNodesMap! ;
1773
1793
_layoutOrderList[childIndex].parentData = childParentData;
1774
1794
_layoutOrderList[childIndex].index = childIndex;
1775
1795
_layoutOrderList[childIndex].renderBox = child;
@@ -1807,7 +1827,7 @@ class _ConstraintRenderBox extends RenderBox
1807
1827
_ConstraintBoxData childParentData =
1808
1828
child.parentData as _ConstraintBoxData ;
1809
1829
childParentData._constrainedNodeMap =
1810
- _processedChildConstraints ! ._processedNodesMap;
1830
+ _childConstraintsCache ! ._processedNodesMap! ;
1811
1831
_paintingOrderList[childIndex].parentData = childParentData;
1812
1832
_paintingOrderList[childIndex].index = childIndex;
1813
1833
_paintingOrderList[childIndex].renderBox = child;
@@ -1831,17 +1851,16 @@ class _ConstraintRenderBox extends RenderBox
1831
1851
assert (() {
1832
1852
if (_debugCheckConstraints) {
1833
1853
List <_ConstrainedNode > nodeList =
1834
- _tempConstrainedNodeMap .values.toList ();
1854
+ _constrainedNodeMap .values.toList ();
1835
1855
_debugCheckConstraintsIntegrity (nodeList);
1836
1856
_debugCheckLoopConstraints (nodeList);
1837
1857
}
1838
1858
return true ;
1839
1859
}());
1840
1860
1841
1861
/// 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 ();
1845
1864
1846
1865
_layoutOrderList.sort ((left, right) {
1847
1866
return left.getDepth () - right.getDepth ();
@@ -2658,9 +2677,9 @@ class _ConstraintRenderBox extends RenderBox
2658
2677
}
2659
2678
}
2660
2679
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;
2664
2683
}
2665
2684
2666
2685
class _ConstrainedNode {
0 commit comments