[MUSIC PLAYING]
EMILY FORTUNA: Hello.
I'm Emily on the Flutter team.
This video 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.
The particular animation you want to do
repeats a couple 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 ones, you need a controller.
For implicit ones, you don't.
We introduced animation controllers
in the previous episode on built-in explicit animation.
So if you'd like to learn more about those,
check that out first.
So 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 generally the classes named FooTransition,
where Foo is the name of the property you're
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, textile, and many more.
Plus, you can compose these widgets
so they can rotate and fade.
But if none of those built-in widgets
can do the trick for what you're looking for,
it's time to build your own using AnimatedWidget
or AnimatedBuilder.
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.
[BLASTING SOUND]
[DIGITAL CHORD]
Yeah, something like that.
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 create the beam shape from that gradient
with a path clipper.
If you want to know more about path clipping,
you can check out my code linked to the description.
I want to create beamed down animation,
starting from the center of that gradient.
And I want to make it repeat.
That means I need to create an explicit animation.
Unfortunately there is no built-in explicit animation
to animate funnel-shaped gradients,
but you know what we do have?
AnimatedWidget, AnimatedBuilder do the trick.
[HORN TOOTING]
To make this animate, I'm going to wrap this gradient code
in the AnimatedBuilder widget.
The gradient code will go in the builder
function, which gets called when the AnimatedBuilder builds.
Now I need to add a controller to drive this animation.
The controller will provide the values
that AnimatedBuilder will use to draw
new versions of the animation frame by frame.
As you saw in the previous episode,
I mix in the single ticker provider state mixing 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 each frame.
Since 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 screen.
Then I pass that controller to the AnimatedBuilder,
and I can see the animation in action.
You may recall in the Tween AnimationBuilder episode
we made use of 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,
you 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 tile parameter.
So we have our animation, but the
build method that contains the AnimatedBuilder
code is a little large.
If your build method's 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 of a build method--
[BUZZER]
--which is a little silly.
Instead, you can accomplish the same animation
by creating a new widget that extends the animated widget.
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 it gets built 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.
I just showed 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 animating.
That's a vote in favor of using AnimatedWidget
whenever possible.
But if your parent widget that creates the animation
is pretty simple, maybe making a separate standalone widget
for your animation is just too much extra code.
In that case, AnimatedBuilder is all you need.
Stay tuned.
In the next video, we'll take a look
under the hood at how animations in Flutter actually work.
For additional documentation on animations,
head on over to flutter.dev.
[MUSIC PLAYING]
ANDREW FITZ GIBBON: Wow.
That was amazing.
Hi.
I'm Fitz from the Flutter team.
On December 11, we're going to have Flutter Interact.
We'll have a livestream here for you to watch,
and I hope you can join us.