ANDREW FITZ GIBBON: All right, let's
pick up where we left off.
Open up the app and check some things off of that list.
Except nothing's checking.
Why isn't my UI changing?
[MUSIC PLAYING]
In the last episode, we talked about what Flutter is
and how to construct a basic app.
We covered what widgets are and even started writing some code.
I used the analogy of a book to describe widgets.
In that example, the book is like our MaterialApp.
It doesn't do anything on its own,
but it sets the theme for the entire rest of the app.
It's not a perfect analogy, though.
And to see why, consider this quote from the documentation.
A widget doesn't do anything other
than describe part of the UI.
And in fact, even in doing that, it never changes.
It's immutable.
But what does that mean?
Let's consider a different analogy.
Suppose you wanted to build a massive and complex layer cake,
kind of like one of those big ones you see on TV.
You don't just throw together a decorative cake, though.
You make a plan, you draw sketches,
and you write or collect recipes.
Often, those recipes are composed of other recipes.
Instead of bake a cake, it might actually
be one recipe for the cake and its batter,
one for the frosting between the layers, one for the decoration,
and one for the little dash figurines
hanging out around the cake.
All together, these make up a plan
which is composed of various recipes
to get various parts of the entire ensemble built.
And while you're baking the cake,
you don't change the recipes.
Instead, you go though the instructions step by step,
exactly as written, to be sure you're building
the same cake every time.
Flutter's widgets are somewhat like these recipes.
They aren't themselves part of an app,
but they describe exactly how to build them.
And every time I want to build one,
I follow the instructions written exactly
and without modifying anything.
So that quote from the documentation
that widgets are descriptions of the UI?
They're just that.
They describe things, and they don't
change while we're using them.
In this way, you use widgets to declare
what you want your app to look like,
and Flutter takes it from there.
But of course, user interfaces and apps
do change as your users use them.
And so how do we take something that by definition never
changes and, well, change things?
Take a look at the task list from the last video.
I declared the items in this list
to be stateless widgets composed of a row, which
is in turn composed of a checkbox and a text label.
Did you try building this code yourself and then
try tapping or clicking on the checkbox?
If so, it probably happened a little like this,
as in it kind of, sort of did nothing.
It just sat there in its original, unchecked state.
Let's open up the code and check out
where the instructions for including the checkbox are.
I took a bit of a shortcut here just to get something running
and hardcoded the checkboxes' required parameters.
This might be why nothing is happening.
The two parameters to the checkbox tell it how to behave.
onChanged expects a function to say what
should the box do when it should change.
The value is a Boolean that says whether or not
the checkbox is checked.
So the UI is behaving exactly as our recipe says it should.
When it's interacted with, do nothing.
And should it be checked?
That value is always false.
As a first attempt at fixing this,
it's tempting to move value into a variable.
And a Dart convention here is to begin
an internal variable name like this with an underscore
and have the onChanged function just set it to the new value.
We'll fix some red squiggly lines along the way
and fix some formatting, and still nothing.
Let's actually read the error the red squiggly was telling us
about.
And with all the finals and constant
here, it feels like this message is
in the same spirit as that quote from the documentation.
Widgets are unchangeable, and so any variables
we have in those classes shouldn't really
be variable, but rather constant.
UI shouldn't be, though.
It should be based on things the user has
done, like checking tasks off of a list when they get finished.
Likewise, whether or not to declare
that a cake is about to disappear
would be based on how many slices have been taken so far.
In app development, this kind of thing
falls under something called state.
And you can think of state as any data
that's needed to create your UI at a certain point in time.
For our checkboxes here, that state
is the Boolean value for whether or not it should be checked.
So far, all of the widgets we've created
have been stateless widgets, that
is, widgets requiring no state.
Our task item widget here needs state, though.
And the easiest way to change it is to ask the editor for help.
Two of the most popular editors, IntelliJ and VS Code,
have support for quick actions in Flutter code.
Put your cursor over the widget and hit that hotkey
to select Convert to Stateful Widget.
The one manual change we'll have to make
is to tell Flutter that the state has changed.
And we do that by adding in a call
to setState, which takes a function that makes the changes
we need.
And there it is.
Congratulations.
You've now created your first stateful widget.
Restart that app, and now watch as the boxes can actually
be checked.
As you look through the new code the editor added in,
there are two questions to answer--
what changed and what didn't.
For the most part, everything's the same.
Aside from the set state we added,
the build method only changed where the label's value is
coming from.
But where the build method exists has changed.
It's now within a state object rather than a widget.
This allows the widget to stay unchangeable, immutable.
Instead of directly building its part of the app,
it delegates that to the new state object.
That way, data like the value variable can stick around,
and we can build the UI based on it.
There's always more to learn about state
and how to organize your app to most effectively access
it and share across widgets throughout your app.
And we'll touch on one of those approaches in the next episode,
then turn our view towards making the app look better.
See you there.
[MUSIC PLAYING]