I have implemented a delayed animation in my welcome screen, but I get this below error in my flutter App. Let me know if there is an error in my code that I can correct and fix this issue.
The error is :
E/flutter (11565): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)]
Unhandled Exception:
'package:flutter/src/animation/animation_controller.dart': Failed
assertion: line 455 pos 7: '_ticker != null':
AnimationController.forward() called after
AnimationController.dispose()
Here is my code:
class DelayedAnimation extends StatefulWidget {
final Widget child;
final int delay;
DelayedAnimation({@required this.child, this.delay});
@override
_DelayedAnimationState createState() => _DelayedAnimationState();
}
class _DelayedAnimationState extends State<DelayedAnimation> with TickerProviderStateMixin {
AnimationController _controller;
Animation<Offset> _animOffset;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 800),
);
final curve = CurvedAnimation(
curve: Curves.decelerate,
parent: _controller,
);
_animOffset = Tween<Offset>(
begin: const Offset(0.0, 0.35),
end: Offset.zero,
).animate(curve);
if (widget.delay == null) {
_controller.forward();
} else {
Timer(Duration(milliseconds: widget.delay), () {
_controller.forward();
});
}
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
child: SlideTransition(
position: _animOffset,
child: widget.child,
),
opacity: _controller,
);
}
}
This problem will often occur when you use a Timer
or Future.delayed
to interact with an AnimationController
. This is the problem. Lets say that delay = 1000
.
The following code tells flutter that in 1000 milliseconds, call forward()
on the animation controller in your DelayedAnimation
widget
Timer(Duration(milliseconds: widget.delay), () {
_controller.forward();
});
However, before this happens, your DelayedAnimation
widget is disposed (this happens, for example, if the user moves to a different screen)
That means that when the Timer
executes, it is calling forward()
on a controller which has been disposed (because the DelayedAnimation
has been disposed)
There are a few solutions.
mounted
property before calling forward:Timer(
Duration(
milliseconds: widget.delay
),
() {
if(mounted) {
_controller.forward();
}
}
);
or 2. Store the Timer when you create it:
_timer = Timer(
Duration(
milliseconds: widget.delay
),
() {
_controller.forward();
}
);
Then cancel it on dispose:
@override
void dispose() {
super.dispose();
_controller.dispose();
_timer?.cancel();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With