Question #349HardWidgets & UI

What is vsync? Explain

#animation#vsync#performance

Answer

Overview

text
vsync
stands for Vertical Sync. In Flutter, it prevents an
text
AnimationController
from wasting resources by updating when the widget is not visible on screen (e.g., when the user navigates to another tab or the app is in the background).


What vsync Does

Without vsync, an animation would update its values every frame even if the widget isn't on screen — wasting CPU and battery.

With vsync, the animation is synced to the screen's refresh rate and pauses automatically when the widget is not visible.


How to Use vsync

You provide

text
vsync
by mixing in
text
SingleTickerProviderStateMixin
or
text
TickerProviderStateMixin
:

dart
class _MyWidgetState extends State<MyWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this, // 'this' is the TickerProvider (vsync)
      duration: Duration(seconds: 2),
    );
  }

  
  void dispose() {
    _controller.dispose(); // Always dispose!
    super.dispose();
  }
}

When to Use Which Mixin

MixinNumber of AnimationControllers
text
SingleTickerProviderStateMixin
Exactly one
text
TickerProviderStateMixin
Multiple
dart
// One animation
class _MyState extends State<MyWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
}

// Multiple animations
class _MyState extends State<MyWidget>
    with TickerProviderStateMixin {
  late AnimationController _controller1;
  late AnimationController _controller2;
}

What Happens Without vsync

dart
// ❌ Without vsync — bad, but won't crash
AnimationController(
  duration: Duration(seconds: 1),
  // No vsync — animation keeps firing even off-screen
)

Flutter will show a warning:

text
AnimationController objects should be disposed when no longer used.


vsync Lifecycle

text
App screen visible → Ticker running → AnimationController updates
App goes background → Ticker paused → AnimationController paused
App returns foreground → Ticker resumes → AnimationController resumes

Full Animation Example with vsync

dart
class PulsingIcon extends StatefulWidget {
  
  _PulsingIconState createState() => _PulsingIconState();
}

class _PulsingIconState extends State<PulsingIcon>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 800),
    )..repeat(reverse: true);

    _animation = Tween<double>(begin: 0.8, end: 1.2).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return ScaleTransition(
      scale: _animation,
      child: Icon(Icons.favorite, size: 48, color: Colors.red),
    );
  }
}

Summary:

text
vsync
connects your
text
AnimationController
to the screen's frame timing, ensuring animations are efficient and pause when the widget is off-screen. Always use
text
SingleTickerProviderStateMixin
for one animation and
text
TickerProviderStateMixin
for multiple.