diff --git a/packages/flutter/lib/src/material/ink_decoration.dart b/packages/flutter/lib/src/material/ink_decoration.dart index 434f7bdda9..b2eba34b8d 100644 --- a/packages/flutter/lib/src/material/ink_decoration.dart +++ b/packages/flutter/lib/src/material/ink_decoration.dart @@ -251,21 +251,9 @@ class _InkState extends State { @override void deactivate() { - _ink?.visible = false; - super.deactivate(); - } - - @override - void reactivate() { - _ink?.visible = true; - super.reactivate(); - } - - @override - void dispose() { _ink?.dispose(); assert(_ink == null); - super.dispose(); + super.deactivate(); } Widget _build(BuildContext context) { diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index 99f9235c5e..a13f7e9be2 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -733,7 +733,6 @@ class _InkResponseState extends State<_InkResponseStateWidget> implements _ParentInkResponseState { Set? _splashes; InteractiveInkFeature? _currentSplash; - bool _active = true; bool _hovering = false; final Map<_HighlightType, InkHighlight?> _highlights = <_HighlightType, InkHighlight?>{}; late final Map> _actionMap = >{ @@ -780,16 +779,7 @@ class _InkResponseState extends State<_InkResponseStateWidget> @override void didUpdateWidget(_InkResponseStateWidget oldWidget) { super.didUpdateWidget(oldWidget); - final InkFeature? validInkFeature = _getSingleInkFeature(); - if (validInkFeature != null && !identical(validInkFeature.controller, Material.of(context)!)) { - _removeAllFeatures(); - if (_hovering && enabled) - updateHighlight(_HighlightType.hover, value: _hovering, callOnHover: false); - _updateFocusHighlights(); - return; - } - - if (enabled != _isWidgetEnabled(oldWidget)) { + if (_isWidgetEnabled(widget) != _isWidgetEnabled(oldWidget)) { if (enabled) { // Don't call wigdet.onHover because many wigets, including the button // widgets, apply setState to an ancestor context from onHover. @@ -799,47 +789,12 @@ class _InkResponseState extends State<_InkResponseStateWidget> } } - InkFeature? _getSingleInkFeature() { - final List inkFeatures = [...?_splashes, ..._highlights.values]; - assert(() { - MaterialInkController? lastController; - for (final InkFeature? inkFeature in inkFeatures) { - if (inkFeature == null) - continue; - final MaterialInkController controller = inkFeature.controller; - if (lastController != null && !identical(controller, lastController)) - return false; - lastController = controller; - } - return true; - }()); - final InkFeature? validInkFeature = inkFeatures.firstWhere((InkFeature? inkFeature) => inkFeature != null, orElse: () => null); - return validInkFeature; - } - @override void dispose() { - _removeAllFeatures(); FocusManager.instance.removeHighlightModeListener(_handleFocusHighlightModeChange); super.dispose(); } - void _removeAllFeatures() { - if (_splashes != null) { - final Set splashes = _splashes!; - _splashes = null; - for (final InteractiveInkFeature splash in splashes) - splash.dispose(); - _currentSplash = null; - } - assert(_currentSplash == null); - for (final _HighlightType highlight in _highlights.keys) { - _highlights[highlight]?.dispose(); - _highlights[highlight] = null; - } - widget.parentState?.markChildInkResponsePressed(this, false); - } - @override bool get wantKeepAlive => highlightsExist || (_splashes != null && _splashes!.isNotEmpty); @@ -875,8 +830,7 @@ class _InkResponseState extends State<_InkResponseStateWidget> void handleInkRemoval() { assert(_highlights[type] != null); _highlights[type] = null; - if (_active) - updateKeepAlive(); + updateKeepAlive(); } if (type == _HighlightType.pressed) { @@ -1059,26 +1013,24 @@ class _InkResponseState extends State<_InkResponseStateWidget> } } - void _setAllFeaturesVisible(bool visible) { - for (final InkFeature? splash in [...?_splashes, ..._highlights.values]) - splash?.visible = visible; - } - @override void deactivate() { - _active = !_active; - _setAllFeaturesVisible(false); + if (_splashes != null) { + final Set splashes = _splashes!; + _splashes = null; + for (final InteractiveInkFeature splash in splashes) + splash.dispose(); + _currentSplash = null; + } + assert(_currentSplash == null); + for (final _HighlightType highlight in _highlights.keys) { + _highlights[highlight]?.dispose(); + _highlights[highlight] = null; + } + widget.parentState?.markChildInkResponsePressed(this, false); super.deactivate(); } - @override - void reactivate() { - _active = !_active; - _setAllFeaturesVisible(true); - updateKeepAlive(); - super.reactivate(); - } - bool _isWidgetEnabled(_InkResponseStateWidget widget) { return widget.onTap != null || widget.onDoubleTap != null || widget.onLongPress != null; } @@ -1249,10 +1201,6 @@ class _InkResponseState extends State<_InkResponseStateWidget> /// during animation. You should avoid using InkWells within [Material] widgets /// that are changing size. /// -/// Animations triggered by an [InkWell] will survive their widget moving due -/// to [GlobalKey] reparenting, as long as the nearest [Material] ancestor is -/// the same before and after the move. -/// /// See also: /// /// * [GestureDetector], for listening for gestures without ink splashes. diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index 98f686075f..1e85a90545 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -544,20 +544,12 @@ class _RenderInkFeatures extends RenderProxyBox implements MaterialInkController canvas.save(); canvas.translate(offset.dx, offset.dy); canvas.clipRect(Offset.zero & size); - for (final InkFeature inkFeature in _inkFeatures!) { - if (inkFeature.visible) - inkFeature._paint(canvas); - } + for (final InkFeature inkFeature in _inkFeatures!) + inkFeature._paint(canvas); canvas.restore(); } super.paint(context, offset); } - - void dispose() { - // [InkFeature.dispose] will eventually call [_inkFeatures!.remove]. - while (_inkFeatures?.isNotEmpty == true) - _inkFeatures!.first.dispose(); - } } class _InkFeatures extends SingleChildRenderObjectWidget { @@ -593,11 +585,6 @@ class _InkFeatures extends SingleChildRenderObjectWidget { ..absorbHitTest = absorbHitTest; assert(vsync == renderObject.vsync); } - - @override - void didUnmountRenderObject(_RenderInkFeatures renderObject) { - renderObject.dispose(); - } } /// A visual reaction on a piece of [Material]. @@ -630,15 +617,6 @@ abstract class InkFeature { bool _debugDisposed = false; - /// Whether or not visual reaction is activated. - /// - /// Change this field will affect whether this InkFeature is render in next - /// frame. - /// - /// For this InkFeature to render properly, it should usually be change in - /// [State.deactivate] and [State.reactivate]. - bool visible = true; - /// Free up the resources associated with this ink feature. @mustCallSuper void dispose() { diff --git a/packages/flutter/lib/src/material/mergeable_material.dart b/packages/flutter/lib/src/material/mergeable_material.dart index 507d68b960..d8b2c306fb 100644 --- a/packages/flutter/lib/src/material/mergeable_material.dart +++ b/packages/flutter/lib/src/material/mergeable_material.dart @@ -584,6 +584,7 @@ class _MergeableMaterialState extends State with TickerProvid } child = AnimatedContainer( + key: _MergeableMaterialSliceKey(_children[i].key), decoration: BoxDecoration(border: border), duration: kThemeAnimationDuration, curve: Curves.fastOutSlowIn, @@ -599,7 +600,6 @@ class _MergeableMaterialState extends State with TickerProvid shape: BoxShape.rectangle, ), child: Material( - key: _MergeableMaterialSliceKey(_children[i].key), type: MaterialType.transparency, child: child, ), diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index ffb94b8fa7..d3b343caf3 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -930,12 +930,6 @@ abstract class State with Diagnosticable { /// It is an error to call [setState] unless [mounted] is true. bool get mounted => _element != null; - /// This field is used tracks [reactivate] and [deactivate], to assert that - /// they are called alternatively. - /// - /// This field is not set in release mode. - bool _debugActive = true; - /// Called when this object is inserted into the tree. /// /// The framework will call this method exactly once for each [State] object @@ -1116,17 +1110,17 @@ abstract class State with Diagnosticable { _element!.markNeedsBuild(); } - /// Whenever the framework removes this [State] object from the tree, the - /// framework will call this method. + /// Called when this object is removed from the tree. /// - /// In some cases, the framework will reinsert the [State] object into - /// another part of the tree (e.g., if the subtree containing this [State] - /// object is grafted from one location in the tree to another). If that - /// happens, the framework will ensure that it calls [reactivate] to give the - /// [State] object a chance to adapt to its new location in the tree. If the - /// framework does reinsert this subtree, it will do so before the end of the - /// animation frame in which the subtree was removed from the tree. For this - /// reason, [State] objects can defer releasing most resources until the + /// The framework calls this method whenever it removes this [State] object + /// from the tree. In some cases, the framework will reinsert the [State] + /// object into another part of the tree (e.g., if the subtree containing this + /// [State] object is grafted from one location in the tree to another). If + /// that happens, the framework will ensure that it calls [build] to give the + /// [State] object a chance to adapt to its new location in the tree. If + /// the framework does reinsert this subtree, it will do so before the end of + /// the animation frame in which the subtree was removed from the tree. For + /// this reason, [State] objects can defer releasing most resources until the /// framework calls their [dispose] method. /// /// Subclasses should override this method to clean up any links between @@ -1142,35 +1136,7 @@ abstract class State with Diagnosticable { /// from the tree permanently. @protected @mustCallSuper - void deactivate() { - assert(() { - _debugActive = !_debugActive; - return !_debugActive; - }()); - } - - /// Called when this object is reactivated. - /// - /// If the [widget] or one of its ancestors has a [GlobalKey], the framework - /// will mark this object as inactive when it is removed and call - /// [deactivate]. - /// - /// If the object is reinserted to the tree in the next frame (e.g. by - /// changing position), it will be marked as active again and this method will be - /// called. - /// - /// See also: - /// - /// * [Element.activate] and [Element.deactivate] for more information about - /// lifecycle. - @protected - @mustCallSuper - void reactivate() { - assert(() { - _debugActive = !_debugActive; - return _debugActive; - }()); - } + void deactivate() { } /// Called when this object is removed from the tree permanently. /// @@ -4811,7 +4777,6 @@ class StatefulElement extends ComponentElement { @override void activate() { super.activate(); - state.reactivate(); // Since the State could have observed the deactivate() and thus disposed of // resources allocated in the build method, we have to rebuild the widget // so that its State can reallocate its resources. diff --git a/packages/flutter/test/material/ink_paint_test.dart b/packages/flutter/test/material/ink_paint_test.dart index 19bc829846..cd08bd514f 100644 --- a/packages/flutter/test/material/ink_paint_test.dart +++ b/packages/flutter/test/material/ink_paint_test.dart @@ -431,67 +431,4 @@ void main() { throw 'Expected: paint.color.alpha == 0, found: ${paint.color.alpha}'; })); }); - - // Regression test for https://github.com/flutter/flutter/issues/6751 - testWidgets('When Ink has a GlobalKey and changes position, splash should not stop', (WidgetTester tester) async { - const Color color = Colors.blue; - const Color splashColor = Colors.green; - - void expectTest(bool painted) { - final PaintPattern paintPattern = paints - ..rect(color: Color(color.value)) - ..circle(color: Color(splashColor.value)); - - expect( - Material.of(tester.element(find.byType(InkWell)))! as RenderBox, - painted ? paintPattern : isNot(paintPattern), - ); - } - - bool wrap = false; - final Key globalKey = GlobalKey(); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: Center( - child: StatefulBuilder( - builder: (BuildContext context, void Function(void Function()) setState) { - Widget child = Ink( - key: globalKey, - color: color, - width: 200.0, - height: 200.0, - child: InkWell( - splashColor: splashColor, - onTap: () { }, - onTapDown: (_) async { - await Future.delayed(const Duration(milliseconds: 50)); - - setState(() { - wrap = !wrap; - }); - } - ), - ); - - if (wrap) { - child = Container( - margin: const EdgeInsets.only(top: 320), - child: child, - ); - } - - return child; - } - ), - ), - ), - )); - final TestGesture testGesture = await tester.startGesture(tester.getRect(find.byType(InkWell)).center); - await tester.pump(const Duration(milliseconds: 60)); - expectTest(true); - await testGesture.up(); - await tester.pumpAndSettle(); - expectTest(false); - }); } diff --git a/packages/flutter/test/material/ink_well_test.dart b/packages/flutter/test/material/ink_well_test.dart index c0bf67f6d2..01e797ee6b 100644 --- a/packages/flutter/test/material/ink_well_test.dart +++ b/packages/flutter/test/material/ink_well_test.dart @@ -1055,6 +1055,118 @@ void main() { await gesture3.up(); }); + testWidgets('When ink wells are reparented, the old parent can display splash while the new parent can not', (WidgetTester tester) async { + final GlobalKey innerKey = GlobalKey(); + final GlobalKey leftKey = GlobalKey(); + final GlobalKey rightKey = GlobalKey(); + + Widget doubleInkWellRow({ + required double leftWidth, + required double rightWidth, + Widget? leftChild, + Widget? rightChild, + }) { + return Material( + child: Directionality( + textDirection: TextDirection.ltr, + child: Align( + alignment: Alignment.topLeft, + child: SizedBox( + width: leftWidth+rightWidth, + height: 100, + child: Row( + children: [ + SizedBox( + width: leftWidth, + height: 100, + child: InkWell( + key: leftKey, + onTap: () {}, + child: Center( + child: SizedBox( + width: leftWidth, + height: 50, + child: leftChild, + ), + ), + ), + ), + SizedBox( + width: rightWidth, + height: 100, + child: InkWell( + key: rightKey, + onTap: () {}, + child: Center( + child: SizedBox( + width: leftWidth, + height: 50, + child: rightChild, + ), + ), + ) + ), + ], + ), + ), + ), + ), + ); + } + + await tester.pumpWidget( + doubleInkWellRow( + leftWidth: 110, + rightWidth: 90, + leftChild: InkWell( + key: innerKey, + onTap: () {}, + ), + ), + ); + final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)))!; + + // Press inner + final TestGesture gesture = await tester.startGesture(const Offset(100, 50), pointer: 1); + await tester.pump(const Duration(milliseconds: 200)); + expect(material, paintsExactlyCountTimes(#drawCircle, 1)); + + // Switch side + await tester.pumpWidget( + doubleInkWellRow( + leftWidth: 90, + rightWidth: 110, + rightChild: InkWell( + key: innerKey, + onTap: () {}, + ), + ), + ); + expect(material, paintsExactlyCountTimes(#drawCircle, 0)); + + // A second pointer presses inner + final TestGesture gesture2 = await tester.startGesture(const Offset(100, 50), pointer: 2); + await tester.pump(const Duration(milliseconds: 200)); + expect(material, paintsExactlyCountTimes(#drawCircle, 1)); + + await gesture.up(); + await gesture2.up(); + await tester.pumpAndSettle(); + + // Press inner + await gesture.down(const Offset(100, 50)); + await tester.pump(const Duration(milliseconds: 200)); + expect(material, paintsExactlyCountTimes(#drawCircle, 1)); + + // Press left + await gesture2.down(const Offset(50, 50)); + await tester.pump(const Duration(milliseconds: 200)); + expect(material, paintsExactlyCountTimes(#drawCircle, 2)); + + await gesture.up(); + await gesture2.up(); + }); + testWidgets("Ink wells's splash starts before tap is confirmed and disappear after tap is canceled", (WidgetTester tester) async { final GlobalKey innerKey = GlobalKey(); await tester.pumpWidget( @@ -1251,231 +1363,4 @@ void main() { textDirection: TextDirection.ltr, )); }); - - // Regression test for https://github.com/flutter/flutter/issues/6751 - testWidgets('When InkWell has a GlobalKey and changes position, splash should not stop', (WidgetTester tester) async { - final GlobalKey<_TestAppState> testAppKey = GlobalKey(); - int frames; - - await tester.pumpWidget(TestApp(key: testAppKey)); - - void expectPaintedCircle(bool painted) { - final PaintPattern paintPattern = paints..circle(); - expect( - Material.of(tester.element(find.byType(InkWell)))! as RenderBox, - painted ? paintPattern : isNot(paintPattern), - ); - } - Future expectSplashContinueAfterMove(bool value) async { - await tester.pump(); - expectPaintedCircle(true); - await tester.pump(const Duration(milliseconds: 10)); - expectPaintedCircle(true); - await tester.pump(const Duration(milliseconds: 40)); - expectPaintedCircle(value); - } - - // InkWell does not have any key, so splash will stop. - testAppKey.currentState!.switchTapChangeWrap(); - await tester.pump(); - await tester.tap(find.byType(InkWell)); - await expectSplashContinueAfterMove(false); - frames = await tester.pumpAndSettle(); - expect(frames, 1); - expectPaintedCircle(false); - - // InkWell has a ValueKey, so splash will also stop. - testAppKey.currentState!.setInkWellKey(const Key('foo')); - await tester.pump(); - await tester.tap(find.byType(InkWell)); - await expectSplashContinueAfterMove(false); - frames = await tester.pumpAndSettle(); - expect(frames, 1); - expectPaintedCircle(false); - - // InkWell has a GlobalKey, so splash will continue. - testAppKey.currentState!.setInkWellKey(GlobalKey()); - await tester.pump(); - await tester.tap(find.byType(InkWell)); - await expectSplashContinueAfterMove(true); - frames = await tester.pumpAndSettle(); - expect(frames > 1, isTrue); - expectPaintedCircle(false); - - testAppKey.currentState!.switchTapDownChangeWrap(); - await tester.pump(); - final TestGesture testGesture = await tester.startGesture(tester.getRect(find.byType(InkWell)).center); - await expectSplashContinueAfterMove(true); - await testGesture.up(); - frames = await tester.pumpAndSettle(); - expect(frames > 1, isTrue); - expectPaintedCircle(false); - }); - - testWidgets('When InkWell/Ancestor has a GlobalKey and ancestor Material is replaced, splash should stop.', (WidgetTester tester) async { - final Key key = GlobalKey(); - bool replaced = false; - - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: StatefulBuilder(builder: (BuildContext context, void Function(void Function()) setState) { - Future changeReplace() async { - await Future.delayed(const Duration(milliseconds: 50)); - setState(() { - replaced = !replaced; - }); - } - return Material( - key: ValueKey(replaced), - child: InkWell( - key: key, - onTap: () { - changeReplace(); - }, - ), - ); - }), - )); - - await tester.tap(find.byType(InkWell)); - await tester.pump(); - await tester.pump(const Duration(milliseconds: 60)); - - final PaintPattern paintPattern = paints..circle(); - expect( - Material.of(tester.element(find.byType(InkWell)))! as RenderBox, - isNot(paintPattern), - ); - }); - - testWidgets('When InkWell/Ancestor has a GlobalKey and ancestor Material is replaced, highlight should always be maintained.', (WidgetTester tester) async { - const Color hoverColor = Color(0xff00ff00); - final Key key = GlobalKey(); - int onHoverCount = 0; - int callChangeReplaceCount = 0; - bool replaced = false; - int frames; - - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: StatefulBuilder(builder: (BuildContext context, void Function(void Function()) setState) { - Future changeReplace() async { - callChangeReplaceCount += 1; - await Future.delayed(const Duration(milliseconds: 50)); - setState(() { - replaced = !replaced; - }); - } - return Container( - margin: replaced ? const EdgeInsets.only(top: 1) : EdgeInsets.zero, - child: Material( - key: ValueKey(replaced), - child: InkWell( - key: key, - hoverColor: hoverColor, - onTap: () {}, - onHover: (bool hovered) { - onHoverCount += 1; - if (hovered) - changeReplace(); - }, - ), - ), - ); - }), - )); - - final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); - await gesture.addPointer(); - addTearDown(gesture.removePointer); - // When replaced is true, InkWell point at the top left is 1. - await gesture.moveTo(Offset.zero); - frames = await tester.pumpAndSettle(); - expect(frames > 1, isTrue); - RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); - expect(inkFeatures, isNot(paints..rect(color: hoverColor))); - expect(onHoverCount, 2); - expect(callChangeReplaceCount, 1); - expect(replaced, true); - - await gesture.moveTo(tester.getCenter(find.byType(InkWell))); - frames = await tester.pumpAndSettle(); - expect(frames > 1, isTrue); - inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); - expect(inkFeatures, paints..rect(color: hoverColor)); - expect(onHoverCount, 3); - expect(callChangeReplaceCount, 2); - expect(replaced, false); - }); -} - -class TestApp extends StatefulWidget { - const TestApp({Key? key}) : super(key: key); - - @override - _TestAppState createState() => _TestAppState(); -} - -class _TestAppState extends State { - bool wrap = false; - bool tapDownChangeWrap = false; - bool tapChangeWrap = false; - Key? inkWellKey; - - @override - Widget build(BuildContext context) { - Widget child = InkWell( - key: inkWellKey, - onTap: () async { - if (tapChangeWrap) { - await changeWrap(); - } - }, - onTapDown: (_) async { - if (tapDownChangeWrap) { - await changeWrap(); - } - }, - ); - - if (wrap) { - child = Container( - child: child, - ); - } - - return Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: child, - ), - ); - } - - Future changeWrap() async { - await Future.delayed(const Duration(milliseconds: 50)); - setState(() { - wrap = !wrap; - }); - } - - void setInkWellKey(Key key) { - setState(() { - inkWellKey = key; - }); - } - - void switchTapDownChangeWrap() { - setState(() { - tapDownChangeWrap = true; - tapChangeWrap = false; - }); - } - - void switchTapChangeWrap() { - setState(() { - tapChangeWrap = true; - tapDownChangeWrap = false; - }); - } } diff --git a/packages/flutter/test/widgets/framework_test.dart b/packages/flutter/test/widgets/framework_test.dart index d33c78623d..972ace39b3 100644 --- a/packages/flutter/test/widgets/framework_test.dart +++ b/packages/flutter/test/widgets/framework_test.dart @@ -1331,28 +1331,24 @@ void main() { expect(key.currentState, isNotNull); expect(state.didChangeDependenciesCount, 1); expect(state.deactivatedCount, 0); - expect(state.reactivatedCount, 0); /// Rebuild with updated value - should call didChangeDependencies await tester.pumpWidget(Inherited(2, child: DependentStatefulWidget(key: key))); expect(key.currentState, isNotNull); expect(state.didChangeDependenciesCount, 2); expect(state.deactivatedCount, 0); - expect(state.reactivatedCount, 0); - // reparent it - should call deactivate, reactivate, didChangeDependencies + // reparent it - should call deactivate and didChangeDependencies await tester.pumpWidget(Inherited(3, child: SizedBox(child: DependentStatefulWidget(key: key)))); expect(key.currentState, isNotNull); expect(state.didChangeDependenciesCount, 3); expect(state.deactivatedCount, 1); - expect(state.reactivatedCount, 1); - // Remove it - should call deactivate, but not reactivate or didChangeDependencies + // Remove it - should call deactivate, but not didChangeDependencies await tester.pumpWidget(const Inherited(4, child: SizedBox())); expect(key.currentState, isNull); expect(state.didChangeDependenciesCount, 3); expect(state.deactivatedCount, 2); - expect(state.reactivatedCount, 1); }); testWidgets('StatefulElement subclass can decorate State.build', (WidgetTester tester) async { @@ -1395,21 +1391,17 @@ void main() { expect(debugDoingBuildOnBuild, isTrue); }); testWidgets('StatefulWidget', (WidgetTester tester) async { - final Key key = GlobalKey(); - late bool debugDoingBuildOnBuild; late bool debugDoingBuildOnInitState; late bool debugDoingBuildOnDidChangeDependencies; late bool debugDoingBuildOnDidUpdateWidget; bool? debugDoingBuildOnDispose; bool? debugDoingBuildOnDeactivate; - bool? debugDoingBuildOnReactivate; await tester.pumpWidget( Inherited( 0, child: StatefulWidgetSpy( - key: key, onInitState: (BuildContext context) { debugDoingBuildOnInitState = context.debugDoingBuild; }, @@ -1435,7 +1427,6 @@ void main() { Inherited( 1, child: StatefulWidgetSpy( - key: key, onDidUpdateWidget: (BuildContext context) { debugDoingBuildOnDidUpdateWidget = context.debugDoingBuild; }, @@ -1451,9 +1442,6 @@ void main() { onDeactivate: (BuildContext context) { debugDoingBuildOnDeactivate = context.debugDoingBuild; }, - onReactivate: (BuildContext context) { - debugDoingBuildOnReactivate = context.debugDoingBuild; - }, ), ), ); @@ -1463,35 +1451,6 @@ void main() { expect(debugDoingBuildOnDidUpdateWidget, isFalse); expect(debugDoingBuildOnDidChangeDependencies, isFalse); expect(debugDoingBuildOnDeactivate, isNull); - expect(debugDoingBuildOnReactivate, isNull); - expect(debugDoingBuildOnDispose, isNull); - - await tester.pumpWidget( - Inherited( - 1, - child: SizedBox( - child: StatefulWidgetSpy( - key: key, - onBuild: (BuildContext context) { - debugDoingBuildOnBuild = context.debugDoingBuild; - }, - onDispose: (BuildContext context) { - debugDoingBuildOnDispose = context.debugDoingBuild; - }, - onDeactivate: (BuildContext context) { - debugDoingBuildOnDeactivate = context.debugDoingBuild; - }, - onReactivate: (BuildContext context) { - debugDoingBuildOnReactivate = context.debugDoingBuild; - }, - ), - ), - ), - ); - - expect(debugDoingBuildOnBuild, isTrue); - expect(debugDoingBuildOnDeactivate, isFalse); - expect(debugDoingBuildOnReactivate, isFalse); expect(debugDoingBuildOnDispose, isNull); await tester.pumpWidget(Container()); @@ -1746,7 +1705,6 @@ class DependentStatefulWidget extends StatefulWidget { class DependentState extends State { int didChangeDependenciesCount = 0; int deactivatedCount = 0; - int reactivatedCount = 0; @override void didChangeDependencies() { @@ -1765,12 +1723,6 @@ class DependentState extends State { super.deactivate(); deactivatedCount += 1; } - - @override - void reactivate() { - super.reactivate(); - reactivatedCount += 1; - } } class SwapKeyWidget extends StatefulWidget { @@ -1858,7 +1810,6 @@ class StatefulWidgetSpy extends StatefulWidget { this.onDidChangeDependencies, this.onDispose, this.onDeactivate, - this.onReactivate, this.onDidUpdateWidget, }) : super(key: key); @@ -1867,7 +1818,6 @@ class StatefulWidgetSpy extends StatefulWidget { final void Function(BuildContext)? onDidChangeDependencies; final void Function(BuildContext)? onDispose; final void Function(BuildContext)? onDeactivate; - final void Function(BuildContext)? onReactivate; final void Function(BuildContext)? onDidUpdateWidget; @override @@ -1887,12 +1837,6 @@ class _StatefulWidgetSpyState extends State { widget.onDeactivate?.call(context); } - @override - void reactivate() { - super.reactivate(); - widget.onReactivate?.call(context); - } - @override void dispose() { super.dispose();