Unverified Commit 63c49c3d authored by Ren You's avatar Ren You Committed by GitHub

Revert "Dispose render objects when owning element is unmounted. (#82883)" (#83790)

This reverts commit c75edc26.
parent c75edc26
...@@ -455,6 +455,7 @@ class RenderSectorSlice extends RenderSectorWithChildren { ...@@ -455,6 +455,7 @@ class RenderSectorSlice extends RenderSectorWithChildren {
} }
class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChildMixin<RenderSector> { class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChildMixin<RenderSector> {
RenderBoxToRenderSectorAdapter({ double innerRadius = 0.0, RenderSector? child }) RenderBoxToRenderSectorAdapter({ double innerRadius = 0.0, RenderSector? child })
: _innerRadius = innerRadius { : _innerRadius = innerRadius {
this.child = child; this.child = child;
...@@ -566,6 +567,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChil ...@@ -566,6 +567,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChil
result.add(BoxHitTestEntry(this, position)); result.add(BoxHitTestEntry(this, position));
return true; return true;
} }
} }
class RenderSolidColor extends RenderDecoratedSector { class RenderSolidColor extends RenderDecoratedSector {
......
...@@ -90,13 +90,6 @@ class SectorAppState extends State<SectorApp> { ...@@ -90,13 +90,6 @@ class SectorAppState extends State<SectorApp> {
}); });
} }
void recursivelyDisposeChildren(RenderObject parent) {
parent.visitChildren((RenderObject child) {
recursivelyDisposeChildren(child);
child.dispose();
});
}
Widget buildBody() { Widget buildBody() {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
...@@ -114,12 +107,7 @@ class SectorAppState extends State<SectorApp> { ...@@ -114,12 +107,7 @@ class SectorAppState extends State<SectorApp> {
Container( Container(
padding: const EdgeInsets.all(4.0), padding: const EdgeInsets.all(4.0),
margin: const EdgeInsets.only(right: 10.0), margin: const EdgeInsets.only(right: 10.0),
child: WidgetToRenderBoxAdapter( child: WidgetToRenderBoxAdapter(renderBox: sectorAddIcon),
renderBox: sectorAddIcon,
onUnmount: () {
recursivelyDisposeChildren(sectorAddIcon);
},
),
), ),
const Text('ADD SECTOR'), const Text('ADD SECTOR'),
], ],
...@@ -134,12 +122,7 @@ class SectorAppState extends State<SectorApp> { ...@@ -134,12 +122,7 @@ class SectorAppState extends State<SectorApp> {
Container( Container(
padding: const EdgeInsets.all(4.0), padding: const EdgeInsets.all(4.0),
margin: const EdgeInsets.only(right: 10.0), margin: const EdgeInsets.only(right: 10.0),
child: WidgetToRenderBoxAdapter( child: WidgetToRenderBoxAdapter(renderBox: sectorRemoveIcon),
renderBox: sectorRemoveIcon,
onUnmount: () {
recursivelyDisposeChildren(sectorRemoveIcon);
},
),
), ),
const Text('REMOVE SECTOR'), const Text('REMOVE SECTOR'),
], ],
...@@ -159,9 +142,6 @@ class SectorAppState extends State<SectorApp> { ...@@ -159,9 +142,6 @@ class SectorAppState extends State<SectorApp> {
child: WidgetToRenderBoxAdapter( child: WidgetToRenderBoxAdapter(
renderBox: sectors, renderBox: sectors,
onBuild: doUpdates, onBuild: doUpdates,
onUnmount: () {
recursivelyDisposeChildren(sectors);
},
), ),
), ),
), ),
......
...@@ -283,15 +283,6 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -283,15 +283,6 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
_RenderEditableCustomPaint? _foregroundRenderObject; _RenderEditableCustomPaint? _foregroundRenderObject;
_RenderEditableCustomPaint? _backgroundRenderObject; _RenderEditableCustomPaint? _backgroundRenderObject;
@override
void dispose() {
_foregroundRenderObject?.dispose();
_foregroundRenderObject = null;
_backgroundRenderObject?.dispose();
_backgroundRenderObject = null;
super.dispose();
}
void _updateForegroundPainter(RenderEditablePainter? newPainter) { void _updateForegroundPainter(RenderEditablePainter? newPainter) {
final _CompositeRenderEditablePainter effectivePainter = newPainter == null final _CompositeRenderEditablePainter effectivePainter = newPainter == null
? _builtInForegroundPainters ? _builtInForegroundPainters
......
...@@ -438,13 +438,6 @@ class RenderImage extends RenderBox { ...@@ -438,13 +438,6 @@ class RenderImage extends RenderBox {
); );
} }
@override
void dispose() {
_image?.dispose();
_image = null;
super.dispose();
}
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
......
...@@ -1111,19 +1111,6 @@ class PipelineOwner { ...@@ -1111,19 +1111,6 @@ class PipelineOwner {
/// The [RenderBox] subclass introduces the opinion that the layout /// The [RenderBox] subclass introduces the opinion that the layout
/// system uses Cartesian coordinates. /// system uses Cartesian coordinates.
/// ///
/// ## Lifecycle
///
/// A [RenderObject] must [dispose] when it is no longer needed. The creator
/// of the object is responsible for disposing of it. Typically, the creator is
/// a [RenderObjectElement], and that element will dispose the object it creates
/// when it is unmounted.
///
/// [RenderObject]s are responsible for cleaning up any expensive resources
/// they hold when [dispose] is called, such as [Picture] or [Image] objects.
/// This includes any [Layer]s that the render object has directly created. The
/// base implementation of dispose will nullify the [layer] property. Subclasses
/// must also nullify any other layer(s) it directly creates.
///
/// ## Writing a RenderObject subclass /// ## Writing a RenderObject subclass
/// ///
/// In most cases, subclassing [RenderObject] itself is overkill, and /// In most cases, subclassing [RenderObject] itself is overkill, and
...@@ -1243,50 +1230,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1243,50 +1230,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
}); });
} }
/// Whether this has been disposed.
///
/// If asserts are disabled, this property is always null.
bool? get debugDisposed {
bool? disposed;
assert(() {
disposed = _debugDisposed;
return true;
}());
return disposed;
}
bool _debugDisposed = false;
/// Release any resources held by this render object.
///
/// The object that creates a RenderObject is in charge of disposing it.
/// If this render object has created any children directly, it must dispose
/// of those children in this method as well. It must not dispose of any
/// children that were created by some other object, such as
/// a [RenderObjectElement]. Those children will be disposed when that
/// element unmounts, which may be delayed if the element is moved to another
/// part of the tree.
///
/// Implementations of this method must end with a call to the inherited
/// method, as in `super.dispose()`.
///
/// The object is no longer usable after calling dispose.
@mustCallSuper
void dispose() {
assert(!_debugDisposed);
_layer = null;
assert(() {
visitChildren((RenderObject child) {
assert(
child.debugDisposed!,
'${child.runtimeType} (child of $runtimeType) must be disposed before calling super.dispose().',
);
});
_debugDisposed = true;
return true;
}());
}
// LAYOUT // LAYOUT
/// Data for use by the parent render object. /// Data for use by the parent render object.
...@@ -1424,10 +1367,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1424,10 +1367,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
bool get _debugCanPerformMutations { bool get _debugCanPerformMutations {
late bool result; late bool result;
assert(() { assert(() {
if (_debugDisposed) {
result = false;
return true;
}
if (owner != null && !owner!.debugDoingLayout) { if (owner != null && !owner!.debugDoingLayout) {
result = true; result = true;
return true; return true;
...@@ -1462,7 +1401,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1462,7 +1401,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
@override @override
void attach(PipelineOwner owner) { void attach(PipelineOwner owner) {
assert(!_debugDisposed);
super.attach(owner); super.attach(owner);
// If the node was dirtied in some way while unattached, make sure to add // If the node was dirtied in some way while unattached, make sure to add
// it to the appropriate dirty list now that an owner is available // it to the appropriate dirty list now that an owner is available
...@@ -1674,7 +1612,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1674,7 +1612,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
/// ///
/// See [RenderView] for an example of how this function is used. /// See [RenderView] for an example of how this function is used.
void scheduleInitialLayout() { void scheduleInitialLayout() {
assert(!_debugDisposed);
assert(attached); assert(attached);
assert(parent is! RenderObject); assert(parent is! RenderObject);
assert(!owner!._debugDoingLayout); assert(!owner!._debugDoingLayout);
...@@ -1744,7 +1681,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1744,7 +1681,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
/// work to update its layout information. /// work to update its layout information.
@pragma('vm:notify-debugger-on-exception') @pragma('vm:notify-debugger-on-exception')
void layout(Constraints constraints, { bool parentUsesSize = false }) { void layout(Constraints constraints, { bool parentUsesSize = false }) {
assert(!_debugDisposed);
if (!kReleaseMode && debugProfileLayoutsEnabled) if (!kReleaseMode && debugProfileLayoutsEnabled)
Timeline.startSync('$runtimeType', arguments: timelineArgumentsIndicatingLandmarkEvent); Timeline.startSync('$runtimeType', arguments: timelineArgumentsIndicatingLandmarkEvent);
...@@ -2104,7 +2040,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2104,7 +2040,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
/// it cannot be the case that _only_ the compositing bits changed, /// it cannot be the case that _only_ the compositing bits changed,
/// something else will have scheduled a frame for us. /// something else will have scheduled a frame for us.
void markNeedsCompositingBitsUpdate() { void markNeedsCompositingBitsUpdate() {
assert(!_debugDisposed);
if (_needsCompositingBitsUpdate) if (_needsCompositingBitsUpdate)
return; return;
_needsCompositingBitsUpdate = true; _needsCompositingBitsUpdate = true;
...@@ -2203,7 +2138,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2203,7 +2138,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
/// layer, thus limiting the number of nodes that [markNeedsPaint] must mark /// layer, thus limiting the number of nodes that [markNeedsPaint] must mark
/// dirty. /// dirty.
void markNeedsPaint() { void markNeedsPaint() {
assert(!_debugDisposed);
assert(owner == null || !owner!.debugDoingPaint); assert(owner == null || !owner!.debugDoingPaint);
if (_needsPaint) if (_needsPaint)
return; return;
...@@ -2288,7 +2222,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2288,7 +2222,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
/// ///
/// This might be called if, e.g., the device pixel ratio changed. /// This might be called if, e.g., the device pixel ratio changed.
void replaceRootLayer(OffsetLayer rootLayer) { void replaceRootLayer(OffsetLayer rootLayer) {
assert(!_debugDisposed);
assert(rootLayer.attached); assert(rootLayer.attached);
assert(attached); assert(attached);
assert(parent is! RenderObject); assert(parent is! RenderObject);
...@@ -2301,7 +2234,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2301,7 +2234,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
} }
void _paintWithContext(PaintingContext context, Offset offset) { void _paintWithContext(PaintingContext context, Offset offset) {
assert(!_debugDisposed);
assert(() { assert(() {
if (_debugDoingThisPaint) { if (_debugDoingThisPaint) {
throw FlutterError.fromParts(<DiagnosticsNode>[ throw FlutterError.fromParts(<DiagnosticsNode>[
...@@ -2525,7 +2457,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2525,7 +2457,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
/// ///
/// See [RendererBinding] for an example of how this function is used. /// See [RendererBinding] for an example of how this function is used.
void scheduleInitialSemantics() { void scheduleInitialSemantics() {
assert(!_debugDisposed);
assert(attached); assert(attached);
assert(parent is! RenderObject); assert(parent is! RenderObject);
assert(!owner!._debugDoingSemantics); assert(!owner!._debugDoingSemantics);
...@@ -2648,7 +2579,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2648,7 +2579,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
/// [RenderObject] as annotated by [describeSemanticsConfiguration] changes in /// [RenderObject] as annotated by [describeSemanticsConfiguration] changes in
/// any way to update the semantics tree. /// any way to update the semantics tree.
void markNeedsSemanticsUpdate() { void markNeedsSemanticsUpdate() {
assert(!_debugDisposed);
assert(!attached || !owner!._debugDoingSemantics); assert(!attached || !owner!._debugDoingSemantics);
if (!attached || owner!._semanticsOwner == null) { if (!attached || owner!._semanticsOwner == null) {
_cachedSemanticsConfiguration = null; _cachedSemanticsConfiguration = null;
...@@ -2894,10 +2824,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2894,10 +2824,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
@override @override
String toStringShort() { String toStringShort() {
String header = describeIdentity(this); String header = describeIdentity(this);
if (_debugDisposed) {
header += ' DISPOSED';
return header;
}
if (_relayoutBoundary != null && _relayoutBoundary != this) { if (_relayoutBoundary != null && _relayoutBoundary != this) {
int count = 1; int count = 1;
RenderObject? target = parent as RenderObject?; RenderObject? target = parent as RenderObject?;
...@@ -3283,7 +3209,6 @@ mixin ContainerRenderObjectMixin<ChildType extends RenderObject, ParentDataType ...@@ -3283,7 +3209,6 @@ mixin ContainerRenderObjectMixin<ChildType extends RenderObject, ParentDataType
} }
} }
} }
/// Insert child into this render object's child list after the given child. /// Insert child into this render object's child list after the given child.
/// ///
/// If `after` is null, then this inserts the child at the start of the list, /// If `after` is null, then this inserts the child at the start of the list,
......
...@@ -3152,6 +3152,7 @@ class RenderRepaintBoundary extends RenderProxyBox { ...@@ -3152,6 +3152,7 @@ class RenderRepaintBoundary extends RenderProxyBox {
return offsetLayer.toImage(Offset.zero & size, pixelRatio: pixelRatio); return offsetLayer.toImage(Offset.zero & size, pixelRatio: pixelRatio);
} }
/// The number of times that this render object repainted at the same time as /// The number of times that this render object repainted at the same time as
/// its parent. Repaint boundaries are only useful when the parent and child /// its parent. Repaint boundaries are only useful when the parent and child
/// paint at different times. When both paint at the same time, the repaint /// paint at different times. When both paint at the same time, the repaint
......
...@@ -6232,11 +6232,6 @@ class DefaultAssetBundle extends InheritedWidget { ...@@ -6232,11 +6232,6 @@ class DefaultAssetBundle extends InheritedWidget {
/// A given render object can be placed at most once in the widget tree. This /// A given render object can be placed at most once in the widget tree. This
/// widget enforces that restriction by keying itself using a [GlobalObjectKey] /// widget enforces that restriction by keying itself using a [GlobalObjectKey]
/// for the given render object. /// for the given render object.
///
/// This widget will call [RenderObject.dispose] on the [renderBox] when it is
/// unmounted. After that point, the [renderBox] will be unusable. If any
/// children have been added to the [renderBox], they must be disposed in the
/// [onUnmount] callback.
class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
/// Creates an adapter for placing a specific [RenderBox] in the widget tree. /// Creates an adapter for placing a specific [RenderBox] in the widget tree.
/// ///
...@@ -6244,7 +6239,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { ...@@ -6244,7 +6239,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
WidgetToRenderBoxAdapter({ WidgetToRenderBoxAdapter({
required this.renderBox, required this.renderBox,
this.onBuild, this.onBuild,
this.onUnmount,
}) : assert(renderBox != null), }) : assert(renderBox != null),
// WidgetToRenderBoxAdapter objects are keyed to their render box. This // WidgetToRenderBoxAdapter objects are keyed to their render box. This
// prevents the widget being used in the widget hierarchy in two different // prevents the widget being used in the widget hierarchy in two different
...@@ -6253,9 +6247,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { ...@@ -6253,9 +6247,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
super(key: GlobalObjectKey(renderBox)); super(key: GlobalObjectKey(renderBox));
/// The render box to place in the widget tree. /// The render box to place in the widget tree.
///
/// This widget takes ownership of the render object. When it is unmounted,
/// it also calls [RenderObject.dispose].
final RenderBox renderBox; final RenderBox renderBox;
/// Called when it is safe to update the render box and its descendants. If /// Called when it is safe to update the render box and its descendants. If
...@@ -6264,25 +6255,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { ...@@ -6264,25 +6255,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
/// tree will be dirty. /// tree will be dirty.
final VoidCallback? onBuild; final VoidCallback? onBuild;
/// Called when it is safe to dispose of children that were manually added to
/// the [renderBox].
///
/// Do not dispose the [renderBox] itself, as it will be disposed by the
/// framework automatically. However, during that process the framework will
/// check that all children of the [renderBox] have also been disposed.
/// Typically, child [RenderObject]s are disposed by corresponding [Element]s
/// when they are unmounted. However, child render objects that were manually
/// added do not have corresponding [Element]s to manage their lifecycle, and
/// need to be manually disposed here.
///
/// See also:
///
/// * [RenderObjectElement.unmount], which invokes this callback before
/// disposing of its render object.
/// * [RenderObject.dispose], which instructs a render object to release
/// any resources it may be holding.
final VoidCallback? onUnmount;
@override @override
RenderBox createRenderObject(BuildContext context) => renderBox; RenderBox createRenderObject(BuildContext context) => renderBox;
...@@ -6290,12 +6262,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { ...@@ -6290,12 +6262,6 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
void updateRenderObject(BuildContext context, RenderBox renderObject) { void updateRenderObject(BuildContext context, RenderBox renderObject) {
onBuild?.call(); onBuild?.call();
} }
@override
void didUnmountRenderObject(RenderObject renderObject) {
assert(renderObject == renderBox);
onUnmount?.call();
}
} }
......
...@@ -3199,13 +3199,10 @@ abstract class Element extends DiagnosticableTree implements BuildContext { ...@@ -3199,13 +3199,10 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
RenderObject? result; RenderObject? result;
void visit(Element element) { void visit(Element element) {
assert(result == null); // this verifies that there's only one child assert(result == null); // this verifies that there's only one child
if (element._lifecycleState == _ElementLifecycle.defunct) { if (element is RenderObjectElement)
return;
} else if (element is RenderObjectElement) {
result = element.renderObject; result = element.renderObject;
} else { else
element.visitChildren(visit); element.visitChildren(visit);
}
} }
visit(this); visit(this);
return result; return result;
...@@ -3844,10 +3841,6 @@ abstract class Element extends DiagnosticableTree implements BuildContext { ...@@ -3844,10 +3841,6 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
/// After this function is called, the element will not be incorporated into /// After this function is called, the element will not be incorporated into
/// the tree again. /// the tree again.
/// ///
/// Any resources this element holds should be released at this point. For
/// example, [RenderObjectElement.unmount] calls [RenderObject.dispose] and
/// nulls out its reference to the render object.
///
/// See the lifecycle documentation for [Element] for additional information. /// See the lifecycle documentation for [Element] for additional information.
/// ///
/// Implementations of this method should end with a call to the inherited /// Implementations of this method should end with a call to the inherited
...@@ -5429,13 +5422,8 @@ abstract class RenderObjectElement extends Element { ...@@ -5429,13 +5422,8 @@ abstract class RenderObjectElement extends Element {
RenderObjectWidget get widget => super.widget as RenderObjectWidget; RenderObjectWidget get widget => super.widget as RenderObjectWidget;
/// The underlying [RenderObject] for this element. /// The underlying [RenderObject] for this element.
///
/// If this element has been [unmount]ed, this getter will throw.
@override @override
RenderObject get renderObject { RenderObject get renderObject => _renderObject!;
assert(_renderObject != null, '$runtimeType unmounted');
return _renderObject!;
}
RenderObject? _renderObject; RenderObject? _renderObject;
bool _debugDoingBuild = false; bool _debugDoingBuild = false;
...@@ -5503,7 +5491,6 @@ abstract class RenderObjectElement extends Element { ...@@ -5503,7 +5491,6 @@ abstract class RenderObjectElement extends Element {
return true; return true;
}()); }());
_renderObject = widget.createRenderObject(this); _renderObject = widget.createRenderObject(this);
assert(!_renderObject!.debugDisposed!);
assert(() { assert(() {
_debugDoingBuild = false; _debugDoingBuild = false;
return true; return true;
...@@ -5781,11 +5768,6 @@ abstract class RenderObjectElement extends Element { ...@@ -5781,11 +5768,6 @@ abstract class RenderObjectElement extends Element {
@override @override
void unmount() { void unmount() {
assert(
!renderObject.debugDisposed!,
'A RenderObject was disposed prior to its owning element being unmounted: '
'$renderObject',
);
final RenderObjectWidget oldWidget = widget; final RenderObjectWidget oldWidget = widget;
super.unmount(); super.unmount();
assert( assert(
...@@ -5794,8 +5776,6 @@ abstract class RenderObjectElement extends Element { ...@@ -5794,8 +5776,6 @@ abstract class RenderObjectElement extends Element {
'RenderObjectElement: $renderObject', 'RenderObjectElement: $renderObject',
); );
oldWidget.didUnmountRenderObject(renderObject); oldWidget.didUnmountRenderObject(renderObject);
_renderObject!.dispose();
_renderObject = null;
} }
void _updateParentData(ParentDataWidget<ParentData> parentDataWidget) { void _updateParentData(ParentDataWidget<ParentData> parentDataWidget) {
......
...@@ -268,8 +268,8 @@ class _SliverPersistentHeaderElement extends RenderObjectElement { ...@@ -268,8 +268,8 @@ class _SliverPersistentHeaderElement extends RenderObjectElement {
@override @override
void unmount() { void unmount() {
renderObject._element = null;
super.unmount(); super.unmount();
renderObject._element = null;
} }
@override @override
......
...@@ -175,7 +175,7 @@ Future<void> main() async { ...@@ -175,7 +175,7 @@ Future<void> main() async {
expect(image.colorBlendMode, BlendMode.color); expect(image.colorBlendMode, BlendMode.color);
}); });
test('RenderImage disposes its image', () async { test('Render image disposes its image', () async {
final ui.Image image = await createTestImage(width: 10, height: 10, cache: false); final ui.Image image = await createTestImage(width: 10, height: 10, cache: false);
expect(image.debugGetOpenHandleStackTraces()!.length, 1); expect(image.debugGetOpenHandleStackTraces()!.length, 1);
...@@ -192,7 +192,7 @@ Future<void> main() async { ...@@ -192,7 +192,7 @@ Future<void> main() async {
expect(image.debugGetOpenHandleStackTraces()!.length, 0); expect(image.debugGetOpenHandleStackTraces()!.length, 0);
}, skip: kIsWeb); // Web doesn't track open image handles. }, skip: kIsWeb); // Web doesn't track open image handles.
test('RenderImage does not dispose its image if setting the same image twice', () async { test('Render image does not dispose its image if setting the same image twice', () async {
final ui.Image image = await createTestImage(width: 10, height: 10, cache: false); final ui.Image image = await createTestImage(width: 10, height: 10, cache: false);
expect(image.debugGetOpenHandleStackTraces()!.length, 1); expect(image.debugGetOpenHandleStackTraces()!.length, 1);
...@@ -208,19 +208,4 @@ Future<void> main() async { ...@@ -208,19 +208,4 @@ Future<void> main() async {
image.dispose(); image.dispose();
expect(image.debugGetOpenHandleStackTraces()!.length, 0); expect(image.debugGetOpenHandleStackTraces()!.length, 0);
}, skip: kIsWeb); // Web doesn't track open image handles. }, skip: kIsWeb); // Web doesn't track open image handles.
test('Render image disposes its image when it is disposed', () async {
final ui.Image image = await createTestImage(width: 10, height: 10, cache: false);
expect(image.debugGetOpenHandleStackTraces()!.length, 1);
final RenderImage renderImage = RenderImage(image: image.clone());
expect(image.debugGetOpenHandleStackTraces()!.length, 2);
renderImage.dispose();
expect(image.debugGetOpenHandleStackTraces()!.length, 1);
expect(renderImage.image, null);
image.dispose();
expect(image.debugGetOpenHandleStackTraces()!.length, 0);
}, skip: kIsWeb); // Web doesn't track open image handles.
} }
...@@ -144,38 +144,6 @@ void main() { ...@@ -144,38 +144,6 @@ void main() {
return context.pushOpacity(offset, 100, painter, oldLayer: oldLayer as OpacityLayer?); return context.pushOpacity(offset, 100, painter, oldLayer: oldLayer as OpacityLayer?);
}); });
}); });
test('RenderObject.dispose sets debugDisposed to true', () {
final TestRenderObject renderObject = TestRenderObject();
expect(renderObject.debugDisposed, false);
renderObject.dispose();
expect(renderObject.debugDisposed, true);
expect(renderObject.toStringShort(), contains('DISPOSED'));
});
test('RenderObject.dispose null the layer on repaint boundaries', () {
final TestRenderObject renderObject = TestRenderObject(allowPaintBounds: true);
// Force a layer to get set.
renderObject.isRepaintBoundary = true;
PaintingContext.repaintCompositedChild(renderObject, debugAlsoPaintedParent: true);
expect(renderObject.debugLayer, isA<OffsetLayer>());
// Dispose with repaint boundary still being true.
renderObject.dispose();
expect(renderObject.debugLayer, null);
});
test('RenderObject.dispose nulls the layer on non-repaint boundaries', () {
final TestRenderObject renderObject = TestRenderObject(allowPaintBounds: true);
// Force a layer to get set.
renderObject.isRepaintBoundary = true;
PaintingContext.repaintCompositedChild(renderObject, debugAlsoPaintedParent: true);
// Dispose with repaint boundary being false.
renderObject.isRepaintBoundary = false;
renderObject.dispose();
expect(renderObject.debugLayer, null);
});
} }
// Tests the create-update cycle by pumping two frames. The first frame has no // Tests the create-update cycle by pumping two frames. The first frame has no
...@@ -220,19 +188,12 @@ class _TestCustomLayerBox extends RenderBox { ...@@ -220,19 +188,12 @@ class _TestCustomLayerBox extends RenderBox {
class TestParentData extends ParentData with ContainerParentDataMixin<RenderBox> { } class TestParentData extends ParentData with ContainerParentDataMixin<RenderBox> { }
class TestRenderObject extends RenderObject { class TestRenderObject extends RenderObject {
TestRenderObject({this.allowPaintBounds = false});
final bool allowPaintBounds;
@override
bool isRepaintBoundary = false;
@override @override
void debugAssertDoesMeetConstraints() { } void debugAssertDoesMeetConstraints() { }
@override @override
Rect get paintBounds { Rect get paintBounds {
assert(allowPaintBounds); // For some tests, this should not get called. assert(false); // The test shouldn't call this.
return Rect.zero; return Rect.zero;
} }
......
...@@ -1619,18 +1619,6 @@ void main() { ...@@ -1619,18 +1619,6 @@ void main() {
await pumpWidget(Container()); await pumpWidget(Container());
expect(states, <String>['deactivate', 'dispose']); expect(states, <String>['deactivate', 'dispose']);
}); });
testWidgets('RenderObjectElement.unmount dispsoes of its renderObject', (WidgetTester tester) async {
await tester.pumpWidget(const Placeholder());
final RenderObjectElement element = tester.allElements.whereType<RenderObjectElement>().first;
final RenderObject renderObject = element.renderObject;
expect(renderObject.debugDisposed, false);
await tester.pumpWidget(Container());
expect(() => element.renderObject, throwsAssertionError);
expect(renderObject.debugDisposed, true);
});
} }
class _WidgetWithNoVisitChildren extends StatelessWidget { class _WidgetWithNoVisitChildren extends StatelessWidget {
......
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