Add CurvedAnimation disposals in some widgets (#143790)

Contributes to https://github.com/flutter/flutter/issues/141198

### Description
- Adds `CurvedAnimation` disposals to `material/chip.dart`, `material/input_decorator.dart`, `material/toggleable.dart`, `widgets/animated_switcher.dart`, `widgets/overscroll_indicator.dart`.
This commit is contained in:
Kostia Sokolovskyi 2024-02-22 20:16:25 +01:00 committed by GitHub
parent 9176f7b6fc
commit f0205354b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 37 additions and 26 deletions

View file

@ -902,11 +902,11 @@ class _RawChipState extends State<RawChip> with MaterialStateMixin, TickerProvid
late AnimationController avatarDrawerController; late AnimationController avatarDrawerController;
late AnimationController deleteDrawerController; late AnimationController deleteDrawerController;
late AnimationController enableController; late AnimationController enableController;
late Animation<double> checkmarkAnimation; late CurvedAnimation checkmarkAnimation;
late Animation<double> avatarDrawerAnimation; late CurvedAnimation avatarDrawerAnimation;
late Animation<double> deleteDrawerAnimation; late CurvedAnimation deleteDrawerAnimation;
late Animation<double> enableAnimation; late CurvedAnimation enableAnimation;
late Animation<double> selectionFade; late CurvedAnimation selectionFade;
bool get hasDeleteButton => widget.onDeleted != null; bool get hasDeleteButton => widget.onDeleted != null;
bool get hasAvatar => widget.avatar != null; bool get hasAvatar => widget.avatar != null;
@ -993,6 +993,11 @@ class _RawChipState extends State<RawChip> with MaterialStateMixin, TickerProvid
avatarDrawerController.dispose(); avatarDrawerController.dispose();
deleteDrawerController.dispose(); deleteDrawerController.dispose();
enableController.dispose(); enableController.dispose();
checkmarkAnimation.dispose();
avatarDrawerAnimation.dispose();
deleteDrawerAnimation.dispose();
enableAnimation.dispose();
selectionFade.dispose();
super.dispose(); super.dispose();
} }

View file

@ -181,9 +181,9 @@ class _BorderContainerState extends State<_BorderContainer> with TickerProviderS
late AnimationController _controller; late AnimationController _controller;
late AnimationController _hoverColorController; late AnimationController _hoverColorController;
late Animation<double> _borderAnimation; late CurvedAnimation _borderAnimation;
late _InputBorderTween _border; late _InputBorderTween _border;
late Animation<double> _hoverAnimation; late CurvedAnimation _hoverAnimation;
late ColorTween _hoverColorTween; late ColorTween _hoverColorTween;
@override @override
@ -218,6 +218,8 @@ class _BorderContainerState extends State<_BorderContainer> with TickerProviderS
void dispose() { void dispose() {
_controller.dispose(); _controller.dispose();
_hoverColorController.dispose(); _hoverColorController.dispose();
_borderAnimation.dispose();
_hoverAnimation.dispose();
super.dispose(); super.dispose();
} }
@ -1902,7 +1904,7 @@ class InputDecorator extends StatefulWidget {
class _InputDecoratorState extends State<InputDecorator> with TickerProviderStateMixin { class _InputDecoratorState extends State<InputDecorator> with TickerProviderStateMixin {
late final AnimationController _floatingLabelController; late final AnimationController _floatingLabelController;
late final Animation<double> _floatingLabelAnimation; late final CurvedAnimation _floatingLabelAnimation;
late final AnimationController _shakingLabelController; late final AnimationController _shakingLabelController;
final _InputBorderGap _borderGap = _InputBorderGap(); final _InputBorderGap _borderGap = _InputBorderGap();
static const OrdinalSortKey _kPrefixSemanticsSortOrder = OrdinalSortKey(0); static const OrdinalSortKey _kPrefixSemanticsSortOrder = OrdinalSortKey(0);
@ -1946,6 +1948,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
@override @override
void dispose() { void dispose() {
_floatingLabelController.dispose(); _floatingLabelController.dispose();
_floatingLabelAnimation.dispose();
_shakingLabelController.dispose(); _shakingLabelController.dispose();
_borderGap.dispose(); _borderGap.dispose();
super.dispose(); super.dispose();

View file

@ -68,8 +68,8 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
/// ///
/// To paint the actual radial reaction, [ToggleablePainter.paintRadialReaction] /// To paint the actual radial reaction, [ToggleablePainter.paintRadialReaction]
/// may be used. /// may be used.
Animation<double> get reaction => _reaction; CurvedAnimation get reaction => _reaction;
late Animation<double> _reaction; late CurvedAnimation _reaction;
/// Controls the radial reaction's opacity animation for hover changes. /// Controls the radial reaction's opacity animation for hover changes.
/// ///
@ -79,8 +79,8 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
/// ///
/// To paint the actual radial reaction, [ToggleablePainter.paintRadialReaction] /// To paint the actual radial reaction, [ToggleablePainter.paintRadialReaction]
/// may be used. /// may be used.
Animation<double> get reactionHoverFade => _reactionHoverFade; CurvedAnimation get reactionHoverFade => _reactionHoverFade;
late Animation<double> _reactionHoverFade; late CurvedAnimation _reactionHoverFade;
late AnimationController _reactionHoverFadeController; late AnimationController _reactionHoverFadeController;
/// Controls the radial reaction's opacity animation for focus changes. /// Controls the radial reaction's opacity animation for focus changes.
@ -90,8 +90,8 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
/// ///
/// To paint the actual radial reaction, [ToggleablePainter.paintRadialReaction] /// To paint the actual radial reaction, [ToggleablePainter.paintRadialReaction]
/// may be used. /// may be used.
Animation<double> get reactionFocusFade => _reactionFocusFade; CurvedAnimation get reactionFocusFade => _reactionFocusFade;
late Animation<double> _reactionFocusFade; late CurvedAnimation _reactionFocusFade;
late AnimationController _reactionFocusFadeController; late AnimationController _reactionFocusFadeController;
/// Whether [value] of this control can be changed by user interaction. /// Whether [value] of this control can be changed by user interaction.
@ -203,9 +203,13 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
@override @override
void dispose() { void dispose() {
_positionController.dispose(); _positionController.dispose();
_position.dispose();
_reactionController.dispose(); _reactionController.dispose();
_reaction.dispose();
_reactionHoverFadeController.dispose(); _reactionHoverFadeController.dispose();
_reactionHoverFade.dispose();
_reactionFocusFadeController.dispose(); _reactionFocusFadeController.dispose();
_reactionFocusFade.dispose();
super.dispose(); super.dispose();
} }

View file

@ -25,7 +25,7 @@ class _ChildEntry {
final AnimationController controller; final AnimationController controller;
// The (curved) animation being used to drive the transition. // The (curved) animation being used to drive the transition.
final Animation<double> animation; final CurvedAnimation animation;
// The currently built transition for this child. // The currently built transition for this child.
Widget transition; Widget transition;
@ -308,7 +308,7 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
reverseDuration: widget.reverseDuration, reverseDuration: widget.reverseDuration,
vsync: this, vsync: this,
); );
final Animation<double> animation = CurvedAnimation( final CurvedAnimation animation = CurvedAnimation(
parent: controller, parent: controller,
curve: widget.switchInCurve, curve: widget.switchInCurve,
reverseCurve: widget.switchOutCurve, reverseCurve: widget.switchOutCurve,
@ -331,7 +331,7 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
required Widget child, required Widget child,
required AnimatedSwitcherTransitionBuilder builder, required AnimatedSwitcherTransitionBuilder builder,
required AnimationController controller, required AnimationController controller,
required Animation<double> animation, required CurvedAnimation animation,
}) { }) {
final _ChildEntry entry = _ChildEntry( final _ChildEntry entry = _ChildEntry(
widgetChild: child, widgetChild: child,
@ -348,6 +348,7 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
_markChildWidgetCacheAsDirty(); _markChildWidgetCacheAsDirty();
}); });
controller.dispose(); controller.dispose();
animation.dispose();
} }
}); });
return entry; return entry;
@ -376,9 +377,11 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
void dispose() { void dispose() {
if (_currentEntry != null) { if (_currentEntry != null) {
_currentEntry!.controller.dispose(); _currentEntry!.controller.dispose();
_currentEntry!.animation.dispose();
} }
for (final _ChildEntry entry in _outgoingEntries) { for (final _ChildEntry entry in _outgoingEntries) {
entry.controller.dispose(); entry.controller.dispose();
entry.animation.dispose();
} }
super.dispose(); super.dispose();
} }

View file

@ -313,12 +313,12 @@ class _GlowController extends ChangeNotifier {
} }
_glowController = AnimationController(vsync: vsync) _glowController = AnimationController(vsync: vsync)
..addStatusListener(_changePhase); ..addStatusListener(_changePhase);
final Animation<double> decelerator = CurvedAnimation( _decelerator = CurvedAnimation(
parent: _glowController, parent: _glowController,
curve: Curves.decelerate, curve: Curves.decelerate,
)..addListener(notifyListeners); )..addListener(notifyListeners);
_glowOpacity = decelerator.drive(_glowOpacityTween); _glowOpacity = _decelerator.drive(_glowOpacityTween);
_glowSize = decelerator.drive(_glowSizeTween); _glowSize = _decelerator.drive(_glowSizeTween);
_displacementTicker = vsync.createTicker(_tickDisplacement); _displacementTicker = vsync.createTicker(_tickDisplacement);
} }
@ -330,6 +330,7 @@ class _GlowController extends ChangeNotifier {
double _paintOffsetScrollPixels = 0.0; double _paintOffsetScrollPixels = 0.0;
// animation values // animation values
late final CurvedAnimation _decelerator;
final Tween<double> _glowOpacityTween = Tween<double>(begin: 0.0, end: 0.0); final Tween<double> _glowOpacityTween = Tween<double>(begin: 0.0, end: 0.0);
late final Animation<double> _glowOpacity; late final Animation<double> _glowOpacity;
final Tween<double> _glowSizeTween = Tween<double>(begin: 0.0, end: 0.0); final Tween<double> _glowSizeTween = Tween<double>(begin: 0.0, end: 0.0);
@ -383,6 +384,7 @@ class _GlowController extends ChangeNotifier {
@override @override
void dispose() { void dispose() {
_glowController.dispose(); _glowController.dispose();
_decelerator.dispose();
_displacementTicker.dispose(); _displacementTicker.dispose();
_pullRecedeTimer?.cancel(); _pullRecedeTimer?.cancel();
super.dispose(); super.dispose();

View file

@ -6,7 +6,6 @@ import 'dart:math' as math;
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
final Matcher doesNotOverscroll = isNot(paints..circle()); final Matcher doesNotOverscroll = isNot(paints..circle());
@ -293,8 +292,6 @@ void main() {
}); });
testWidgets('Nested overscrolls do not throw exceptions', testWidgets('Nested overscrolls do not throw exceptions',
// TODO(polina-c): clean up leaks, https://github.com/flutter/flutter/issues/134787 [leaks-to-clean]
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(),
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,

View file

@ -5,7 +5,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
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 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('CustomScrollView restoration', (WidgetTester tester) async { testWidgets('CustomScrollView restoration', (WidgetTester tester) async {
@ -264,8 +263,6 @@ void main() {
}); });
testWidgets('PageView restoration', testWidgets('PageView restoration',
// TODO(polina-c): clean up leaks, https://github.com/flutter/flutter/issues/134787 [leaks-to-clean]
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(),
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
TestHarness( TestHarness(