[MUSIC PLAYING] ANDREW BROGDON: Hey, everybody. I'm Andrew from
the Flutter team. And in this video,
I'm going to tell you all about Flutter's
stateful widgets-- what makes them different
from stateless widgets, how state objects
work, and more. This is actually the second in
a run of videos we're doing. So if you haven't
seen the first one, I recommend scrolling down
to the video description below, where we
have a link to it. If you have seen
that first video, you're probably pretty familiar
with stateless widgets. They're an immutable
configuration, or blueprint, so to speak, for an
element, which is what's actually placed on screen. Now, if you're like me, you
hear that and you think, immutable configs are
great, but I'm not writing an app that's just
going to draw itself and stop. What about data that changes? How do I track that
and update my UI? Well, that's where
stateful widget comes in. It provides immutable
configuration info and a state object that can
change over time and trigger rebuilds of the UI. Let's take a look at some code,
and I'll show you how it works. Here's a basic stateless widget. It takes a name and
count in its constructor, and it builds a text
widget to display them. Super simple. But let's say I need that
count to change over time. I can't change anything inside
a stateless widget, right? Count is final. So I'll turn this into
a stateful widget. Now I've got a couple classes,
a widget and a state object. The widget is responsible
for two things-- holding onto that immutable
name value, which won't change, and creating the state object. The state object,
for its part, holds the count value,
which you'll notice is no longer tagged as final. It can change, and
the state object now builds child widgets. In this case, the
text widget that will display the name and count. To get a handle on
how this really works, let's take a look at the
widget and element trees. If you recall from
our previous video, it's the element
tree that actually represents what's on screen. The widgets are just
blueprints for those elements. Now, for stateless widgets, the
process of getting on screen is pretty straightforward. You give Flutter a stateless
widget, and Flutter says, no problem, I can display this. I just need an element. Hey, widget, can you
make an element for me? The stateless widget
creates a stateless element, and it's mounted into
the element tree. If that stateless widget has
child widgets that it builds, elements are made
from them, they get mounted, and so on down. With a stateful widget,
there's an extra step. Just like before,
first comes the widget. But when Flutter asks
it to create an element, it returns a stateful element. That stateful element then
goes back to the widget and says, hey, can you
make a state object for me? Which is what that
createState method is for. That method kicks out
a new state object, and the element holds onto it. Now it's time to
build child widgets, so stateful element calls the
state object's Build method. If we take a look at the code
from before, you'll see why. In order to build a text
with the correct string, we need the name property
from the widget and the count property from the state object. Because the state object
maintains a reference to the widget for widgets
maintaining state, it can access both
values and use them to construct the text widget. And there it is. Text is stateless, so it
creates a stateless element which gets mounted in the tree. Now, technically, text has
a few children of its own to help with accessibility and
actually rendering the text, but for this example I'm just
going to keep things simple and stop right here. So everything's built, and our
element tree is ready to go. All right, let's take another
look at the state object. Right now, nothing in here is
actually updating the state. Nothing's changing
that count property. But if I drop in a
gesture detector, I can use the setState
method in the state object to make a change. setState is a way for you to set
properties on the state object and trigger updates to the UI. You give it a function
that makes the changes, and the state object
runs it and make sure the UI gets
rebuilt afterwards. If we go back to the
diagram, when setState runs, the count gets incremented. Plus-- and here's
the important bit-- the state object marks
its element as dirty, meaning it will rebuild its
children on the next frame. And here, I'm using frame
in the graphics card, 60-frames-per-second sense. When that next
frame rolls around, just like before,
stateful element calls the Build
method in the state object to rebuild the children,
and out pops a new text widget that shows the new count. The old text widget goes away,
and in comes the new one. And here's a cool part. Because that new widget is
the same type as the old one-- they're both text-- the
stateless element stays right where it is, and
just updates itself to reference the new widget. So that's a basic example
of how state objects can hold data that changes over time
and rebuild child widgets when it does. But there's another
really useful thing about state objects-- they have a long lifespan. They can remain attached
to the element tree even when the original widget
gets replaced by a new one, as long as that new one
is of the same type. For example, if the
ItemCounter widget itself would rebuild, maybe from a
change above it in the tree, the original ItemCounter
widget goes away, but since the new one is
the same type of widget, the stateful element
and state object stay right where they are. They survive the
change in widgets, and just mark themselves
dirty so their children get rebuilt. Then the state
object's Build method kicks out a new text widget
using its count value, but with the new ItemCounter
widget's name value. The old text widget goes
away, the new one's mounted, and the stateless
element for the text stays right where it is. So that's how state
can be maintained even after the widget
that made the state object has been replaced. It's kind of like stateful
hot reload, right? You can push new
code to your device without changing where you are
in the app and what's going on. Here, we're building new
widgets with new properties, but that state stays the same. I'm not using it
in this example, but there's even a
method in the State class called didUpdateWidget
that you can override if your state
object needs to know when its widget gets replaced. Animated Container,
for example, uses this to know when it should
start animating the change from one config to another. So as you can see,
stateful widgets give you the power to
track data over time and update your app's UI to
match, which is really handy. The ironic thing is, though,
as you get better and better with Flutter,
you'll probably find yourself writing fewer and
fewer stateful widgets. One of the reasons is that a
lot of the common use cases have already been implemented. For example, say you
have a stream of data, and you want a stateful
widget that rebuilds whenever the stream emits a new value. Well, that's a stream
builder, and it's part of the Flutter framework. Another reason is
that if you've got a bunch of nested
stateful widgets, passing data through all those
build methods and constructors can get cumbersome. Fortunately, there's
another type of widget that makes it easy
to access data stored near the top of the tree even
if you're 100 widgets down. It's called InheritedWidget,
and we'll tell you all about it in the next video in the series. In the meantime,
for more information about Flutter and all its many
widgets, head to flutter.io. [MUSIC PLAYING]