Unverified Commit 82afe3ea authored by xubaolin's avatar xubaolin Committed by GitHub

Clear the cached data of `RenderBox` if its parent re-layout (#101493)

parent 55881f7a
...@@ -2348,8 +2348,7 @@ abstract class RenderBox extends RenderObject { ...@@ -2348,8 +2348,7 @@ abstract class RenderBox extends RenderObject {
}()); }());
} }
@override bool _clearCachedData() {
void markNeedsLayout() {
if ((_cachedBaselines != null && _cachedBaselines!.isNotEmpty) || if ((_cachedBaselines != null && _cachedBaselines!.isNotEmpty) ||
(_cachedIntrinsicDimensions != null && _cachedIntrinsicDimensions!.isNotEmpty) || (_cachedIntrinsicDimensions != null && _cachedIntrinsicDimensions!.isNotEmpty) ||
(_cachedDryLayoutSizes != null && _cachedDryLayoutSizes!.isNotEmpty)) { (_cachedDryLayoutSizes != null && _cachedDryLayoutSizes!.isNotEmpty)) {
...@@ -2361,14 +2360,30 @@ abstract class RenderBox extends RenderObject { ...@@ -2361,14 +2360,30 @@ abstract class RenderBox extends RenderObject {
_cachedBaselines?.clear(); _cachedBaselines?.clear();
_cachedIntrinsicDimensions?.clear(); _cachedIntrinsicDimensions?.clear();
_cachedDryLayoutSizes?.clear(); _cachedDryLayoutSizes?.clear();
if (parent is RenderObject) { return true;
markParentNeedsLayout(); }
return; return false;
} }
@override
void markNeedsLayout() {
if (_clearCachedData() && parent is RenderObject) {
markParentNeedsLayout();
return;
} }
super.markNeedsLayout(); super.markNeedsLayout();
} }
@override
void layout(Constraints constraints, {bool parentUsesSize = false}) {
if (hasSize && constraints != this.constraints &&
_cachedBaselines != null && _cachedBaselines!.isNotEmpty) {
// The cached baselines data may need update if the constraints change.
_cachedBaselines?.clear();
}
super.layout(constraints, parentUsesSize: parentUsesSize);
}
/// {@macro flutter.rendering.RenderObject.performResize} /// {@macro flutter.rendering.RenderObject.performResize}
/// ///
/// By default this method sets [size] to the result of [computeDryLayout] /// By default this method sets [size] to the result of [computeDryLayout]
......
...@@ -5,7 +5,11 @@ ...@@ -5,7 +5,11 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'rendering_tester.dart';
class RenderTestBox extends RenderBox { class RenderTestBox extends RenderBox {
late Size boxSize;
int calls = 0;
double value = 0.0; double value = 0.0;
double next() { double next() {
value += 1.0; value += 1.0;
...@@ -19,9 +23,23 @@ class RenderTestBox extends RenderBox { ...@@ -19,9 +23,23 @@ class RenderTestBox extends RenderBox {
double computeMinIntrinsicHeight(double width) => next(); double computeMinIntrinsicHeight(double width) => next();
@override @override
double computeMaxIntrinsicHeight(double width) => next(); double computeMaxIntrinsicHeight(double width) => next();
@override
void performLayout() {
size = constraints.biggest;
boxSize = size;
}
@override
double? computeDistanceToActualBaseline(TextBaseline baseline) {
calls += 1;
return boxSize.height / 2.0;
}
} }
void main() { void main() {
TestRenderingFlutterBinding.ensureInitialized();
test('Intrinsics cache', () { test('Intrinsics cache', () {
final RenderBox test = RenderTestBox(); final RenderBox test = RenderTestBox();
...@@ -68,4 +86,52 @@ void main() { ...@@ -68,4 +86,52 @@ void main() {
expect(test.getMinIntrinsicWidth(0.0), equals(1.0)); expect(test.getMinIntrinsicWidth(0.0), equals(1.0));
}); });
// Regression test for https://github.com/flutter/flutter/issues/101179
test('Cached baselines should be cleared if its parent re-layout', () {
double viewHeight = 200.0;
final RenderTestBox test = RenderTestBox();
final RenderBox baseline = RenderBaseline(
baseline: 0.0,
baselineType: TextBaseline.alphabetic,
child: test,
);
final RenderConstrainedBox root = RenderConstrainedBox(
additionalConstraints: BoxConstraints.tightFor(width: 200.0, height: viewHeight),
child: baseline,
);
layout(RenderPositionedBox(
child: root,
));
BoxParentData? parentData = test.parentData as BoxParentData?;
expect(parentData!.offset.dy, -(viewHeight / 2.0));
expect(test.calls, 1);
// Trigger the root render re-layout.
viewHeight = 300.0;
root.additionalConstraints = BoxConstraints.tightFor(width: 200.0, height: viewHeight);
pumpFrame();
parentData = test.parentData as BoxParentData?;
expect(parentData!.offset.dy, -(viewHeight / 2.0));
expect(test.calls, 2); // The layout constraints change will clear the cached data.
final RenderObject parent = test.parent! as RenderObject;
expect(parent.debugNeedsLayout, false);
// Do not forget notify parent dirty after the cached data be cleared by `layout()`
test.markNeedsLayout();
expect(parent.debugNeedsLayout, true);
pumpFrame();
expect(parent.debugNeedsLayout, false);
expect(test.calls, 3); // Self dirty will clear the cached data.
parent.markNeedsLayout();
pumpFrame();
expect(test.calls, 3); // Use the cached data if the layout constraints do not change.
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment