Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:02,240 --> 00:00:09,620
What's this state thing I mentioned? In general, state is data or information
2
00:00:09,620 --> 00:00:17,390
your app or your widgets in your app use. State can be things like a username or in our case, the index
3
00:00:17,390 --> 00:00:19,650
of the question we want to show.
4
00:00:19,670 --> 00:00:25,310
So app wide state would be things like is the user authenticated or if we're building an app that users
5
00:00:25,310 --> 00:00:27,550
can use to find new jobs,
6
00:00:27,560 --> 00:00:34,790
we could have the overall jobs we loaded from a server. widget state could be things like the current
7
00:00:34,790 --> 00:00:37,530
user input or are we currently loading data and
8
00:00:37,560 --> 00:00:44,690
do we want to show a spinner or as in our application, the widget state of the app widget we have could
9
00:00:44,690 --> 00:00:45,050
be
10
00:00:45,050 --> 00:00:52,120
which question is currently selected and that state can and typically will change in an application.
11
00:00:53,150 --> 00:00:55,210
However as the name suggests
12
00:00:55,250 --> 00:01:01,400
since we're extending a stateless widget here, this widget can't have state.
13
00:01:01,400 --> 00:01:08,270
Now that might sound very restrictive and strange, since we typically have interactive applications where
14
00:01:08,270 --> 00:01:10,020
things should change,
15
00:01:10,040 --> 00:01:17,570
why would we have widgets that can't change? Typically in your Flutter application,
16
00:01:17,590 --> 00:01:23,170
you will have more than one widget and we'll soon have more than one which is here as well and some widgets
17
00:01:23,260 --> 00:01:28,900
are only there to output something, like that text widget which is built into Flutter. This is a widget
18
00:01:28,930 --> 00:01:33,520
which has no state in it, it gets the text from outside
19
00:01:33,520 --> 00:01:39,400
passed in, that is passed in when the widget is created so it never changes whilst the widget is
20
00:01:39,790 --> 00:01:45,970
there and it just outputs the text, it does nothing else, it doesn't react to clicks on the text or anything
21
00:01:45,970 --> 00:01:46,850
like that.
22
00:01:47,020 --> 00:01:53,170
Therefore, text would be a perfect stateless widget and indeed it is and a lot of the widgets are only
23
00:01:53,170 --> 00:02:00,580
concerned with outputting data with certain styles, certain colors or in a certain structure. Some widgets
24
00:02:00,580 --> 00:02:06,520
however need to change data, like our app here, we want to change that question index and for this, we
25
00:02:06,520 --> 00:02:11,860
can convert that stateless widget into a so-called stateful widget.
26
00:02:11,990 --> 00:02:17,960
The difference between stateless and stateful widgets is that in a stateless widget, we have our
27
00:02:17,960 --> 00:02:22,190
widget and the build method which is used to render the UI.
28
00:02:22,190 --> 00:02:26,270
Now we can pass in data from outside into the stateless
29
00:02:26,270 --> 00:02:29,250
widget through the constructor of that class,
30
00:02:29,270 --> 00:02:35,960
so of the widget class, we'll do this later too. And this data can change and actually Flutter would rebuild
31
00:02:36,320 --> 00:02:39,090
that widget when that external data changes
32
00:02:39,110 --> 00:02:42,120
but inside of the widget class, the data will never change,
33
00:02:42,140 --> 00:02:47,670
we can only receive new data from outside and that will basically rebuild the widget.
34
00:02:47,900 --> 00:02:53,440
Now a stateful widget also has a build method that builds a widget and that renders a UI
35
00:02:53,460 --> 00:02:59,930
therefore but here, we can also get our input data, so data passed in through the constructor of the widget
36
00:02:59,930 --> 00:03:00,920
class
37
00:03:00,920 --> 00:03:07,100
but we also can have some internal state and that's the core thing here and this widget will get
38
00:03:07,100 --> 00:03:14,060
re-rendered, so the user interface will get updated by Flutter whenever either that external, that input data
39
00:03:14,090 --> 00:03:18,290
changed or when our internal state changed and
40
00:03:18,290 --> 00:03:25,340
that's the core difference. Here we really just have a MyApp widget which doesn't take any input data,
41
00:03:25,370 --> 00:03:31,040
so it doesn't even take that but it certainly can't have internal data, internal state because it's a
42
00:03:31,120 --> 00:03:32,430
stateless widget.
43
00:03:32,430 --> 00:03:38,080
Now how can we turn this into a stateful widget now? For turning this into a stateful widget, you could
44
00:03:38,080 --> 00:03:43,600
think that you simply rename this into stateful widget but now we have an error because it's not that
45
00:03:43,600 --> 00:03:44,340
simple.
46
00:03:45,060 --> 00:03:52,020
You also can refactor this in Visual Studio Code and Android Studio if you have the Flutter extensions
47
00:03:52,020 --> 00:04:03,210
installed which you should have. Then you can check your key bindings and search for refactor and you should
48
00:04:03,210 --> 00:04:08,380
find a key binding which you can use to get refactoring suggestions
49
00:04:08,430 --> 00:04:14,730
and if you place your cursor on stateless widgets, if you click on that and you then use that key binding,
50
00:04:15,060 --> 00:04:19,360
here I get the suggestion of converting this to a stateful widget.
51
00:04:19,530 --> 00:04:24,300
We could do that and in the future, we will take advantage of this because it's super fast
52
00:04:24,300 --> 00:04:30,820
but here I won't do that because I want to show you what makes up a stateful widget step-by-step.
53
00:04:30,960 --> 00:04:37,410
Now the first step is indeed that you rename this to stateful widget, stateful widget is a widget,
54
00:04:37,470 --> 00:04:41,280
is a class provided by the material package here,
55
00:04:41,280 --> 00:04:45,070
so this exists so you can use that.
56
00:04:45,190 --> 00:04:49,150
Now however, a stateful widget is a bit more complex than a stateless widget.
57
00:04:49,210 --> 00:04:50,920
It's actually not just one class,
58
00:04:50,920 --> 00:04:53,870
it's instead a combination of two classes.
59
00:04:53,920 --> 00:04:57,790
So let's close the curly brace of our first class here and
60
00:04:58,180 --> 00:05:03,780
let's add a second class with all of that content down there, with the build method and so on
61
00:05:03,820 --> 00:05:12,990
being part of that second class. This is now typically named MyAppState, not my app state but your widget
62
00:05:13,080 --> 00:05:15,630
name plus state after it,
63
00:05:15,630 --> 00:05:24,150
so in this case MyAppState because my widget here is also named MyApp. MyAppState now extends state
64
00:05:25,420 --> 00:05:27,760
and now you can open your curly brace again.
65
00:05:28,140 --> 00:05:35,640
State again is a class imported from material.dart and state is a generic class.
66
00:05:35,640 --> 00:05:38,040
Now comes the more complex part,
67
00:05:38,400 --> 00:05:40,500
why do we have two classes
68
00:05:40,500 --> 00:05:48,390
first of all? Because the way Flutter works internally, into which I'll dive a bit deeper later, is that
69
00:05:48,610 --> 00:05:51,450
the widget itself can be recreated,
70
00:05:51,450 --> 00:05:54,900
this class can be recreated, when the external data changes,
71
00:05:54,900 --> 00:05:55,980
this will be recreated
72
00:05:55,980 --> 00:05:59,670
basically. The state however is persistent,
73
00:05:59,730 --> 00:06:06,250
it's attached to that widget, so it's attached to that element in the user interface which you see
74
00:06:06,690 --> 00:06:11,970
but unlike that class here, it's technically not recreated
75
00:06:12,120 --> 00:06:18,660
and that's important for storing your state so that when you question index changes and the external
76
00:06:18,660 --> 00:06:25,920
data passed into the widget itself changes, only that is rewritten, is rebuilt and our data here is
77
00:06:25,920 --> 00:06:27,040
not reset
78
00:06:27,300 --> 00:06:32,700
and if that's not entirely clear yet, it will become clear once we start passing data into the widget
79
00:06:32,700 --> 00:06:34,080
itself.
80
00:06:34,080 --> 00:06:38,660
So we have that separation so that this data here, the state can be persistent
81
00:06:38,700 --> 00:06:46,650
whilst this widget itself can be rebuilt. Now we need to tell Flutter that this state class belongs
82
00:06:46,650 --> 00:06:47,850
to this widget class
83
00:06:47,850 --> 00:06:53,830
however, to us humans, to us developers, it's clear because of the naming, MyAppState and MyApp
84
00:06:53,970 --> 00:06:55,690
but the naming is just a convention,
85
00:06:55,800 --> 00:07:02,220
it's not a rule and therefore, Flutter does not take the name as an indicator that this class here belongs
86
00:07:02,220 --> 00:07:03,930
to this widget.
87
00:07:03,930 --> 00:07:07,320
Instead to set up a connection, we need two things.
88
00:07:07,320 --> 00:07:15,030
First of all, state is a generic type so we should add angled brackets there and in between, we add a pointer
89
00:07:15,450 --> 00:07:16,770
at our class here,
90
00:07:16,770 --> 00:07:19,260
so here I add MyApp.
91
00:07:19,260 --> 00:07:24,360
This tells Dart and Flutter that this state belongs to the MyApp class,
92
00:07:24,400 --> 00:07:27,270
so this is one part of the connection.
93
00:07:27,300 --> 00:07:30,680
The second part has to be done here inside of MyApp class,
94
00:07:30,690 --> 00:07:33,190
so inside of the widget. There,
95
00:07:33,450 --> 00:07:38,610
we have to add a new method, the createState method.
96
00:07:38,610 --> 00:07:44,130
Now here, I get a suggestion by my IDE and if I hit enter, it automatically adds it for me.
97
00:07:44,850 --> 00:07:50,460
Now createState as you can see is a method that takes no arguments but that in the end has to return
98
00:07:50,460 --> 00:07:54,440
a state object which is connected to a stateful widget.
99
00:07:54,520 --> 00:07:56,480
Now that's exactly what we have down there,
100
00:07:56,490 --> 00:08:01,980
it's an object that's of type state in the end because it inherits from state and that is connected
101
00:08:01,980 --> 00:08:04,520
to MyApp which is a stateful widget.
102
00:08:04,530 --> 00:08:10,140
So here, we want to return a new MyAppState
103
00:08:10,150 --> 00:08:17,840
object. Here we create a new object based on that class, which also knows about this class and therefore
104
00:08:17,840 --> 00:08:22,280
we now connected the two pieces, the two classes from both ends.
105
00:08:22,280 --> 00:08:27,500
Here we also have override again because createState is a method provided by stateful widget,
106
00:08:27,650 --> 00:08:31,530
it needs to be overriden and again to be clear that we are doing this deliberately,
107
00:08:31,550 --> 00:08:37,570
we add @Override here. Now we have the connection set up from both sides
108
00:08:37,850 --> 00:08:43,670
and now with this change, the build method is now inside the state, not inside the widget because the
109
00:08:43,670 --> 00:08:47,070
state holds the data that is used by the build method.
110
00:08:47,090 --> 00:08:54,650
With this now changed and nothing else changed, if we now save this and we restart our application because
111
00:08:54,650 --> 00:08:57,700
if you do such a transformation, hot reload typically doesn't work
112
00:08:57,710 --> 00:09:03,510
so you need to do a full restart with that green arrow here or the shortcut which you chose there.
113
00:09:03,530 --> 00:09:11,760
Now with that, if you go back and you click Answer 1, please watch the what's your favorite color text,
114
00:09:11,870 --> 00:09:13,700
still nothing changes.
115
00:09:13,730 --> 00:09:19,790
We see the output go up there with the print statement which is still part of answer question but still
116
00:09:19,790 --> 00:09:21,550
nothing changes in the UI.
117
00:09:22,700 --> 00:09:28,670
Well the reason for that is that still, even with this transformation to stateful widget and state, Flutter
118
00:09:28,670 --> 00:09:32,570
doesn't automatically update and re-render the user interface
119
00:09:32,570 --> 00:09:38,510
just because we tap the button and that's good because for performance, it would not be that great if
120
00:09:38,510 --> 00:09:46,820
Flutter would re-render the user interface on every tap of the user. If we tap somewhere and Flutter takes
121
00:09:46,820 --> 00:09:53,670
this as an indicator to re-render everything, then our app would certainly have a horrible performance.
122
00:09:53,750 --> 00:10:00,260
Instead we have to tell Flutter that we're about to change the state and that when this state is changed,
123
00:10:00,500 --> 00:10:09,120
it should re-render this widget. We do that by wrapping the code where we do change data inside of our
124
00:10:09,120 --> 00:10:14,820
state, that is reflected in the user interface and the question index is of course reflected because it
125
00:10:14,820 --> 00:10:17,080
controls which question is shown.
126
00:10:17,130 --> 00:10:25,110
So when we change that, we wrap this in a set state function. Set state is a function or a method to be
127
00:10:25,110 --> 00:10:32,550
precise that is provided by that state class which we inherit and set state takes a function, typically
128
00:10:32,550 --> 00:10:33,890
an anonymous function,
129
00:10:34,020 --> 00:10:39,960
so a function here with no arguments and then a function body and inside of this function which we
130
00:10:39,960 --> 00:10:42,100
passed to the set state function,
131
00:10:42,180 --> 00:10:48,570
so a function that takes a function as an argument, that's just how it is, inside of this function, we
132
00:10:48,570 --> 00:10:58,470
move that code or we change our property in this case, the property which also is used in build. Now
133
00:10:58,480 --> 00:11:03,960
with that if we now save this and we do a full restart,
134
00:11:07,630 --> 00:11:12,910
if you now watch what's your favorite color and I click Answer 1, you see now it changes to what's
135
00:11:12,910 --> 00:11:15,190
your favorite animal
136
00:11:15,190 --> 00:11:22,220
and this now happens because of set state and us using a stateful widget. Now throughout this course, we'll
137
00:11:22,230 --> 00:11:28,110
work with both, stateless and stateful widgets. As you learned, the majority of widgets will actually
138
00:11:28,110 --> 00:11:33,600
be stateless because more often than not, you're just concerned with outputting something in a nice
139
00:11:33,600 --> 00:11:34,210
way
140
00:11:34,440 --> 00:11:39,570
but occasionally, you need to change data, you need to react to user input and change something and then
141
00:11:39,630 --> 00:11:45,840
we'll use stateful widgets which are the other core type of widget Flutter supports and knows. By the
142
00:11:45,840 --> 00:11:50,280
way, please note that if you press this more than once, you of course get an error because then you change
143
00:11:50,310 --> 00:11:55,590
question index to two and you would try to access the third question which we of course don't have.
15906
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.