Flutter Fix: Resolving "Multiple tickers were created" Error
Have you ever tried adding a second animation to your Flutter screen, only to be hit with a crash? You aren't alone! It's a classic "gotcha" moment for many Flutter developers.
Recently, while building the Emergency 108 app, I ran into this exact issue when trying to animate both a background gradient and an SOS button on the same screen. Here's exactly what happened and how I fixed it.
The Problem
I had a HomeScreen that initially had just one animation controller for a pulsing SOS button. Naturally, I used SingleTickerProviderStateMixin.
class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateMixin {
late AnimationController _sosController;
@override
void initState() {
super.initState();
_sosController = AnimationController(vsync: this, duration: Duration(seconds: 1));
}
}
Later, I decided to add a second animation for a dynamic background gradient. I added a second controller:
late AnimationController _backgroundController;
@override
void initState() {
super.initState();
_sosController = AnimationController(vsync: this, duration: Duration(seconds: 1));
// CRASH HAPPENS HERE
_backgroundController = AnimationController(vsync: this, duration: Duration(seconds: 3));
}
The Error
As soon as the app reloaded, it crashed with this error:
FlutterError: Multiple tickers were created by a SingleTickerProviderStateMixin.
The error message is actually quite helpful. It tells us exactly what's wrong: SingleTickerProviderStateMixin is designed to provide a single ticker (the clock that drives an animation) for a single controller. When we passed vsync: this to the second controller, it tried to create a second ticker, which the mixin strictly forbids.
The Solution
The fix is incredibly simple: Change SingleTickerProviderStateMixin to TickerProviderStateMixin.
The TickerProviderStateMixin is the more powerful sibling that allows for multiple animation controllers in a single widget.
The Fix
// 1. Change the Mixin
class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
late AnimationController _sosController;
late AnimationController _backgroundController;
@override
void initState() {
super.initState();
// 2. Now 'vsync: this' works for BOTH controllers!
_sosController = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
_backgroundController = AnimationController(
vsync: this,
duration: const Duration(seconds: 3),
);
}
@override
void dispose() {
// 3. Don't forget to dispose BOTH controllers to prevent memory leaks
_sosController.dispose();
_backgroundController.dispose();
super.dispose();
}
}
Summary
- Use
SingleTickerProviderStateMixinwhen you have exactly oneAnimationController. It's slightly more efficient. - Use
TickerProviderStateMixinwhen you need two or moreAnimationControllersin the same widget.
That's it! A one-word change to keep your complex animations running smoothly. Happy coding! 🚀