Reputation: 277067
When using AnimationController, what is the purpose of that vsync
parameter?
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> with SingleTickerProviderStateMixin {
AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this, // Why do we need this?
);
}
// ...
}
Upvotes: 7
Views: 2282
Reputation: 277067
AnimationController's vsync
parameter has one purpose: Controlling the progress of the animation based on external factors.
There are typically three main usages:
vsync
, this allows tests to skip frames to target a very specific state of the animation. This is both precise and doesn't involve waiting for real-time.The last scenario is the main reason why our widgets need to that SingleTickerProviderStateMixin. Knowing what widget is associated with the animation matters. We can't just use a TickerProvider obtained from the root widget of our application.
Through that vsync
, this will avoid scenarios where our widget is no longer visible (for example if another route is pushed on the top of it), but the animation is still playing and therefore makes our screen to keep refreshing
A way of seeing that behavior is by using the "performance overlay" devtool combined with widgets like CircularProgressIndicator, which internally uses AnimationController.
If we use Opacity
to hide our indicator (which doesn't pause animations):
Opacity(
opacity: 0,
child: CircularProgressIndicator(),
)
Then the performance overlay shows that our screen keeps refreshing:
Now, if we add a TickerMode (implicitly done by widgets like Visibility and Navigator), we can pause the animation, which stops the unnecessary refresh:
Opacity(
opacity: 0,
child: TickerMode(
enabled: false,
child: CircularProgressIndicator(),
),
),
Upvotes: 12