When should I useAnimatedBuilder or AnimatedWidget?

Emily Fortuna
Flutter
Published in
5 min readJan 19, 2020

We know you have many choices when you fly, I mean animate, in Flutter, so thank you for choosing AnimatedBuilder and AnimatedWidget. Wait, what? No! Flutter has many different animation widgets, but unlike commercial airlines, each type of widget is right for a different type of job. Sure, you can accomplish the same animation in a couple of different ways, but using the right animation widget for the job will make your life much easier.

This article covers why you might want to use AnimatedBuilder or AnimatedWidget versus other animation widgets, and how to use them. Suppose you want to add an animation to your app. This article is part of a series, walking through why you might want to use each type of animation widget. The particular animation you want to do repeats a couple of times or needs to be able to pause and resume in response to something, like a finger tap. Because your animation needs to repeat, or stop and start, you’ll need to use an explicit animation.

As a reminder, we have two broad categories of animations in Flutter: explicit and implicit. For explicit animations, you need an animation controller. For implicit animations, you don’t. We introduced animation controllers in the previous article about built-in explicit animations. If you’d like to learn more about those, please check that out first.

So, if you’ve determined that you need an explicit animation, there are a whole host of explicit animation classes for you to choose from. Those are the classes generally named FooTransition, where Foo is the name of the property you are trying to animate. I recommend seeing if you can use one of those widgets to accomplish your needs first, before diving into the deep world of AnimatedWidget and AnimatedBuilder. There’s an amazing selection of widgets for pretty much anything you can think of — rotation, position, alignment, fading, text style, and many more. Plus, you can compose these widgets, so that you can rotate and fade. But, if none of those built-in widgets can do what you’re looking for, it’s time to build your own using AnimatedWidget or AnimatedBuilder.

A flow chart for understanding what animation to use in any scenario. This article focuses on the two bottom blue end-states, AnimatedBuilder and AnimatedWidget.

Specific Example

To make this more concrete, let’s walk through a specific scenario: I want to write an app with an alien spaceship and have a spaceship beam animation.

Maybe something exactly like this.

I drew a spaceship beam with a gradient that fades from yellow to transparent, beginning the fade at the very center of the gradient. Then, I created the “beam” shape from that gradient with a path clipper.

I want to create a “beam down” animation, starting from the center of that gradient, and I want to make it repeat. That means I’ll need to create an explicit animation. Unfortunately there’s no built-in explicit animation to animate funnel-shaped gradients, but you know what we do have… AnimatedWidget and AnimatedBuilder to do the trick!

AnimatedBuilder

To make the beam animate, I am going to wrap this gradient code in an AnimatedBuilder widget. The gradient code goes in the builder function, which gets called when the AnimatedBuilder builds.

Next I need to add a controller to drive this animation. The controller provides the values that AnimatedBuilder uses to draw new versions of the animation frame by frame. As you saw in the previous article, I mix in the SingleTickerProviderStateMixin class and instantiate the controller in the initState function so that it only gets created once. I create the controller in initState, rather than the build method, because I don’t want to create this controller multiple times — I want it to provide new values to animate with for each frame! Because I created a new object in initState, I add a dispose method and tell Flutter that it can get rid of that controller when the parent widget is no longer on the screen.

Then, I pass that controller to the AnimatedBuilder, and my animation runs as expected!

You may recall in the TweenAnimationBuilder article that we used the child parameter as a performance optimization, and we can do that with AnimatedBuilder too. Basically, if we have an object that never changes over the course of the animation, we can build it ahead of time, and just pass it to AnimatedBuilder.

In this specific case, a better way to accomplish the same thing is to give BeamClipper a const constructor and just make it const. It’s less code, and the object is created at compile time, making things even faster. Sometimes, though, you’ll be coding something that doesn’t have a const constructor, and that’s a good case for when to make use of that optional child parameter.

AnimatedWidget

So, we have our animation, but the build method that contains the AnimatedBuilder code is a little large. If your build method is starting to get hard to read, it’s time to refactor your code!

You could pull your AnimatedBuilder code out into a separate widget, but then you just have a build method inside a build method, which is a little silly. Instead, you can accomplish the same animation by creating a new widget that extends AnimatedWidget. I’ll name my widget BeamTransition to be consistent with the FooTransition naming convention for explicit animations. I pass in the animation controller to BeamTransition and reuse the body of the AnimatedBuilder’s builder function.

Just like AnimatedBuilder, if appropriate, I can add a child parameter to my widget as a performance optimization so that it builds ahead of time, instead of every time I animate. Just a reminder though, in this example, making my BeamClipper take a const constructor is the best way to go.

So really, which one should I to use?

We just saw how AnimatedBuilder and AnimatedWidget can both be used to accomplish the same type of explicit animations when you can’t find a built-in explicit animation to do what you want. So, which one should you use? It’s really a matter of taste. Generally speaking, I recommend making individual widgets, each with a separate job — which in this case is animation.

That’s a vote in favor of using AnimatedWidget whenever possible. However, if your parent widget that creates the animation controller is pretty simple, maybe making a separate standalone widget just for your animation is too much extra code. In that case, AnimatedBuilder is all that you need.

This is an article version of the video below. If you prefer videos, click below:

Articles in this series:

--

--