Flutter code creating laggy animation. What is wrong here?

5,058

The whole purpose of using AnimationController is to listen to its events - that's what AnimatedBuilder does and rebuilds its subtree accordingly.

I will post here my overall recommendations on what to change in the code.


Remove setState - that's what makes your entire layout rebuild all over again, i.e. lags.

Also trigger _animeController listeners, i.e. AnimatedBuilder in your case - to rebuild itself.

accelerometerEvents.listen((AccelerometerEvent event) {
  var a = ((event.x * 100).round() / 100).clamp(-1.0, 1.0) * -1;
  var b = ((event.y * 100).round() / 100).clamp(-1.0, 1.0);
  if ((x - a).abs() > 0.02 || (y - b).abs() > 0.02) {
    x = a; y = b;
    _animeController.value = _animeController.value; // Trigger controller's listeners
  }
});

Start animation in initState, instead of build. This is the second thing that produces lags in your case. .forward triggers rebuild of your widgets, which leads to an infinite loop.

@override
void initState() {
  super.initState();
  _animeController.forward();
}

Use child property of your AnimatedBuilder to save up resources on rebuilding the avatar block every time. Also I'm not sure what Scaffold is here for - let's remove it if it's not needed.

AnimatedBuilder(
  animation: _animeController,
  builder: (context, child) => Transform(
    transform: Matrix4.translationValues(_anime.value * width * x, _anime.value * height * y, 0.0),
    child: child,
  ),
  child: Center(
    child: CircleAvatar(
      radius: 15.0,
      backgroundColor: Colors.green,
    ),
  ),
);

Follow Official Animations Tutorial to master Flutter animations.

Let me know if this helps.

Share:
5,058
Shikhir Aggarwal
Author by

Shikhir Aggarwal

Updated on November 30, 2022

Comments

  • Shikhir Aggarwal
    Shikhir Aggarwal over 1 year

    I have created a flutter widget that moves the circle with accelerometer. It is very laggy as I have to use setState to change the position of the circle when phone is moved. Is there an alternative to creating this?

    I have used AnimatedBuilder here but not sure how that can change the position of circle when device is moved smoothly.

    class _AnimationWidgetState extends State<AnimationWidget>
        with TickerProviderStateMixin {
      AnimationController _animeController;
      Animation _anime;
      double x = 0.0, y = 0.0;
      @override
      void initState() {
        super.initState();
        _animeController =
            AnimationController(vsync: this, duration: const Duration(seconds: 2));
        _anime = Tween(begin: 0.5, end: 0.5).animate(
            CurvedAnimation(parent: _animeController, curve: Curves.ease));
        accelerometerEvents.listen((AccelerometerEvent event) {
          var a = ((event.x * 100).round() / 100).clamp(-1.0, 1.0) * -1;
          var b = ((event.y * 100).round() / 100).clamp(-1.0, 1.0);
          if ((x - a).abs() > 0.02 || (y - b).abs() > 0.02) {
            setState(() {
              x = a; y = b;
            });
          }
        });
      }
    
      @override
      void dispose() {
        _animeController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        _animeController.forward();
        final double width = MediaQuery.of(context).size.width;
        final double height = MediaQuery.of(context).size.height;
        return AnimatedBuilder(
          animation: _animeController,
          builder: (context, child) {
            return Scaffold(
              body: Transform(
                transform: Matrix4.translationValues(
                    _anime.value * width * x, _anime.value * height * y, 0.0),
                child: Center(
                  child: CircleAvatar(
                    radius: 15.0,
                    backgroundColor: Colors.green,
                  ),
                ),
              ),
            );
          },
        );
      }
    }
    

    Animation is not at all smooth. This is because I have to use setState but the movement of circle is working as desired.