Sitemap
Flutter Community

Articles and Stories from the Flutter Community

Flutter Laggy Animations: How Not To

3 min readMar 26, 2019

--

Creating animations in Flutter is really fun and easy, but there is one bad practice that might make those animations laggy: .

Bad Practice: AnimationController and setState

When using in a , you might be tempted to do the following:

void initState() {
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 1),
)
..addListener(() => setState(() {}));
}

To animate a from left to right by 100 pixels:

Transform.translate(
offset: Offset(100 * _controller.value, 0),
child: Placeholder(key: Key('animated')),
),

This will animate the by it will also rebuild all other widgets in the :

Column(
children: [
Placeholder(key: Key('1')), // rebuilds
Placeholder(key: Key('2')), // rebuilds
Placeholder(key: Key('3')), // rebuilds
Transform.translate( // rebuilds
offset: Offset(100 * _controller.value, 0),
child: Placeholder(key: Key('animated')),
),

],
),

This is the build timeline[1]:

AnimationController and setState

Those widgets are light but in a production application, with bigger widgets, there might be a performance issue.

Good Practice: AnimatedBuilder without setState

First, you need to remove :

void initState() {
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 1),
);
// No
addListener(...)
}

Then wrap your transition into an :

AnimatedBuilder(
animation: _controller,
builder: (_, child) {

return Transform.translate(
offset: Offset(100 * _controller.value, 0),
child: child,
);
},
child: Placeholder(key: Key('animated')),
),

That’s all. Because we’ve removed the is not rebuilding. The only widget that will rebuild is :

AnimatedBuilder without setState

Bad Practice: Opacity with AnimatedBuilder

You could do the same trick with changing opacity and using :

AnimatedBuilder(
animation: _controller,
builder: (_, child) {
return Opacity(
opacity: _controller.value,
child: child,
);

},
child: Placeholder(key: Key('animated')),
),
Opacity with AnimatedBuilder

Changing opacity is a quite expensive animation, that’s why there is a better way of doing that.

Good Practice: Opacity with FadeTransition

There is a special opacity transition that is optimized for performance:

FadeTransition(
opacity: _controller,

child: Placeholder(key: Key('animated')),
),

With this approach, the build is never called:

Opacity with FadeTransition

Build phase is usually placed between Animation and Layout phase — here you can notice now it’s gone.

Conclusion

Try always to avoid using with like this:

Don’t use setState like this

Additionally, check out transitions.dart within Flutter framework to see what other optimised transition you can use.

All the source code for those examples can be found here.

Thanks

for the help with the post

Sidenote:

If you wonder why and widgets are not visible in the timeline, it is because they are not backed up by but create directly for performance improvement.

Remember that Build phase comes from .

[1] To enable Build phase profiling in the timeline, enable debugProfileBuildsEnabled flag in your Flutter method

--

--

Flutter Community
Flutter Community

Published in Flutter Community

Articles and Stories from the Flutter Community

Tomek Polański
Tomek Polański

Written by Tomek Polański

Passionate mobile developer. One thing I like more than learning new things: sharing them

Responses (4)