Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
0
1
00:00:00,330 --> 00:00:08,300
Now in the last lesson we used our scratch.dart file to learn more about futures and async and await.
1
2
00:00:08,490 --> 00:00:13,740
But we don't need this file anymore so you can either delete it or you can keep it around for reference
2
3
00:00:13,740 --> 00:00:14,580
in the future.
3
4
00:00:14,640 --> 00:00:16,490
It won't affect your project.
4
5
00:00:16,590 --> 00:00:23,460
Now let's head back into our loading screen and if we take a look at the code now, it should make a bit
5
6
00:00:23,460 --> 00:00:25,500
more sense to you.
6
7
00:00:25,570 --> 00:00:32,530
You can see that we're creating a new geolocator object that comes from geolocator.dart. And then
7
8
00:00:32,530 --> 00:00:37,110
we're using that object to get the current position. We're calling getCurrentPosition
8
9
00:00:37,810 --> 00:00:45,520
and this is a method that's inside geolocator. And we provide the amount of accuracy we want for this
9
10
00:00:45,520 --> 00:00:46,460
location.
10
11
00:00:46,690 --> 00:00:53,770
And we're going to choose low so that we don't use up all the battery. And because it takes time to get
11
12
00:00:53,770 --> 00:00:55,370
the current position
12
13
00:00:55,390 --> 00:01:01,570
this method is asynchronous and it will happen independently of whatever else you decide to try and
13
14
00:01:01,570 --> 00:01:09,560
do. But because in most cases we can only proceed forwards with for example printing the position we
14
15
00:01:09,560 --> 00:01:14,230
got back or with using that position in getting some weather data,
15
16
00:01:14,360 --> 00:01:22,010
then we're adding the async keyword to modify our function. And that gives us access to the await keyword
16
17
00:01:22,100 --> 00:01:30,700
which basically says wait until this completes before you continue doing anything. If we didn't have
17
18
00:01:30,700 --> 00:01:37,650
this await keyword, then we could still have a position but it won't be an actual position.
18
19
00:01:37,810 --> 00:01:40,650
It will be a future position.
19
20
00:01:40,720 --> 00:01:43,240
It's just like that order number.
20
21
00:01:43,240 --> 00:01:45,290
It will have a value in the future
21
22
00:01:45,310 --> 00:01:52,300
once this process completes. But at the point where this code is called or when it's triggered, this is
22
23
00:01:52,300 --> 00:01:53,460
just a receipt.
23
24
00:01:53,470 --> 00:01:55,760
It's not an actual coffee.
24
25
00:01:55,900 --> 00:02:03,220
And right now if I was to print out this position variable, it won't be an actual position that actually
25
26
00:02:03,220 --> 00:02:09,510
comes out. And we can show that by changing this from running scratch.dart to main.dart.
26
27
00:02:09,610 --> 00:02:20,040
And now if I press run and I go ahead and click on get location, then you can see that what's being printed
27
28
00:02:20,040 --> 00:02:24,320
in my console on the main.dart, so we can close down scratch.dart
28
29
00:02:24,330 --> 00:02:31,920
if you want, is an instance of future position. This is kind of like you promise your friends to go and
29
30
00:02:31,920 --> 00:02:36,540
grab them a coffee and all you did is come back with the receipt.
30
31
00:02:36,660 --> 00:02:38,430
Now they're not going to want the receipt.
31
32
00:02:38,430 --> 00:02:40,590
They're going to want the actual coffee.
32
33
00:02:40,740 --> 00:02:47,880
So that's why we're adding that await keyword in front of the method call to say that, wait for this
33
34
00:02:47,880 --> 00:02:51,380
to finish before you assign this value to the position.
34
35
00:02:51,840 --> 00:02:58,620
So that way we actually get an actual position or an actual coffee, rather than just the promise of a
35
36
00:02:58,620 --> 00:03:01,860
coffee that's going to be there in the future.
36
37
00:03:01,920 --> 00:03:08,880
And now if I click on get location, you can see the actual location gets printed rather than just a future.
37
38
00:03:10,410 --> 00:03:14,950
So it's all very well and good that we can get the location when we press on this button.
38
39
00:03:15,000 --> 00:03:23,640
But what if we wanted the location as soon as our screen loads up? Because in our weather app, as soon
39
40
00:03:23,640 --> 00:03:29,030
as we open up the app, it's going to trying and detect our location and based off that location, it's gonna
40
41
00:03:29,070 --> 00:03:30,120
get the weather.
41
42
00:03:30,120 --> 00:03:35,750
It doesn't make sense to force the user to press a button to say get weather or get location,
42
43
00:03:35,760 --> 00:03:46,980
that seems a bit extra. So how would I call get location if I wanted it to happen as soon as my screen
43
44
00:03:47,070 --> 00:03:51,630
loads up? Well in order to do this
44
45
00:03:51,630 --> 00:03:55,980
we have to learn about widget lifecycles.
45
46
00:03:55,980 --> 00:04:01,410
We know that stateless widgets are basically just like very simple Lego blocks right?
46
47
00:04:01,410 --> 00:04:03,240
You can't saw them in half,
47
48
00:04:03,240 --> 00:04:04,480
you can't change them.
48
49
00:04:04,560 --> 00:04:11,400
You can't do anything with them unless you decide to destroy them and create a new one.
49
50
00:04:11,700 --> 00:04:18,340
And you have to keep destroying and creating new ones every time you want a change in a stateless widget.
50
51
00:04:18,360 --> 00:04:24,300
So for these widgets, their lifecycle methods are very simple. There's only one that you should be concerned
51
52
00:04:24,300 --> 00:04:29,270
about and that's the build method. When the widget gets built
52
53
00:04:29,280 --> 00:04:32,820
this method will be called and inside here,
53
54
00:04:32,820 --> 00:04:39,180
you will create whatever appearance or widget you want to show up on screen.
54
55
00:04:39,270 --> 00:04:46,830
Now on the other hand, we also have our stateful widgets and we know that these stateful widgets can
55
56
00:04:46,830 --> 00:04:52,410
be combined and we can track the state using a state object.
56
57
00:04:52,440 --> 00:05:00,340
Now that state object is there keep track of variables such as what is the configuration of my widgets,
57
58
00:05:00,450 --> 00:05:02,820
what are the properties of my widgets.
58
59
00:05:02,910 --> 00:05:11,270
And I can change all of those variables by using a set state and it will update my app. Now
59
60
00:05:11,280 --> 00:05:19,000
in this case, the state object actually lives a lot longer and so it's got more lifecycle methods.
60
61
00:05:19,020 --> 00:05:25,930
There is an init state, which gets triggered when that state initially gets initialized.
61
62
00:05:26,020 --> 00:05:31,140
There's of course the build method which gets triggered when the widgets are actually built and will
62
63
00:05:31,140 --> 00:05:38,310
show up on screen. And then there's a deactivate method which gets called when that stateful widget
63
64
00:05:38,340 --> 00:05:39,550
gets destroyed.
64
65
00:05:41,150 --> 00:05:48,680
So just as we humans are born and we grow up we go through different life stages and then we also die,
65
66
00:05:48,710 --> 00:05:55,940
so do our stateful widgets. But we can tap into each of those stages in the lifecycle if we wanted different
66
67
00:05:55,940 --> 00:05:59,330
things to happen at various times.
67
68
00:05:59,360 --> 00:06:05,180
Now I just want to show you when these lifecycle methods will get triggered. And to do so, I'm pulling
68
69
00:06:05,180 --> 00:06:09,670
up that previous file that we had, the navigation demo that we used earlier on.
69
70
00:06:09,970 --> 00:06:12,310
Now you don't have to write any of the code,
70
71
00:06:12,350 --> 00:06:14,900
I just want to show you what actually happens.
71
72
00:06:14,990 --> 00:06:21,870
It's enough to just follow along. Here we still got our screen 1 which is a stateless widget.
72
73
00:06:21,940 --> 00:06:29,330
We've got our screen 2 which is currently a stateful widget. And I've made our app start out at a screen
73
74
00:06:29,390 --> 00:06:30,940
1 which is the first route.
74
75
00:06:31,490 --> 00:06:38,590
So when I run my app, I head over to the screen 1 which only has a single button that pushes me onto
75
76
00:06:38,650 --> 00:06:40,300
screen 2.
76
77
00:06:40,400 --> 00:06:47,300
Now once I'm on screen 2, I want to be able to show you when these lifecycle methods actually get called.
77
78
00:06:47,870 --> 00:06:54,950
Inside our state object, I'm going to tap into a number of methods that come from the parent class, the
78
79
00:06:54,950 --> 00:07:00,440
state class. One of those is the initState method.
79
80
00:07:00,440 --> 00:07:06,830
And if we click on this initState, hold down CONTROL + J or CONTROL + Q, you can see that this
80
81
00:07:06,830 --> 00:07:11,240
is called when an object is inserted into the tree.
81
82
00:07:11,340 --> 00:07:18,800
And this means that when we create our stateful widget as soon as it's inserted into the tree, it's
82
83
00:07:18,800 --> 00:07:20,210
going to call initState.
83
84
00:07:20,210 --> 00:07:22,580
So this is the first thing that happens.
84
85
00:07:22,690 --> 00:07:32,000
So inside here I'm going to add a print statement saying 'initState called'. And that will print whenever
85
86
00:07:32,330 --> 00:07:39,020
this method gets triggered. And it will get triggered automatically at a particular stage in the life
86
87
00:07:39,170 --> 00:07:41,150
of this state object.
87
88
00:07:41,150 --> 00:07:44,030
Now the second one that gets triggered,
88
89
00:07:44,030 --> 00:07:49,160
so the second point in the lifecycle, is going to be the build method.
89
90
00:07:49,160 --> 00:07:54,950
Now inside here, I'm also going to add a print statement saying 'build called'.
90
91
00:07:57,880 --> 00:08:03,400
And finally there's also another method that comes from the parent class that I want to show you which
91
92
00:08:03,400 --> 00:08:12,350
is called deactivate. And deactivate will get triggered when this stateful widget gets destroyed.
92
93
00:08:12,370 --> 00:08:15,380
So let's add a print statement in here as well.
93
94
00:08:18,730 --> 00:08:27,490
Now let's go ahead and click run for our changes to go through. And in our console you can see that as
94
95
00:08:27,490 --> 00:08:32,320
soon as I click on this button, I should head over to screen 2.
95
96
00:08:32,830 --> 00:08:38,860
Now as soon as that stateful widget is created and inserted into the widget tree, initState gets
96
97
00:08:38,860 --> 00:08:39,330
called.
97
98
00:08:39,340 --> 00:08:40,830
So that gets printed in here.
98
99
00:08:41,410 --> 00:08:48,370
And then as soon as it builds all of the widgets inside the screen which is just my button and my scaffold
99
100
00:08:48,380 --> 00:08:57,070
etc. then we get billed called. Now every time I make a change in the screen or I change one of the properties
100
101
00:08:57,370 --> 00:09:01,750
that the widgets depend on, then build will get called again and again and again.
101
102
00:09:01,780 --> 00:09:05,420
And this is one of the most frequently used lifecycle methods.
102
103
00:09:05,620 --> 00:09:14,160
But at the very end when I click on go back to screen 1, screen 2 is going to pop off,
103
104
00:09:14,170 --> 00:09:16,330
that means it's going to be destroyed.
104
105
00:09:16,330 --> 00:09:18,140
It will no longer exist.
105
106
00:09:18,280 --> 00:09:22,300
And that is the time when deactivate will get called.
106
107
00:09:22,360 --> 00:09:28,770
So there are other lifecycle methods but these are probably the most useful and the ones that you'll
107
108
00:09:28,780 --> 00:09:32,660
actually come across and need when you're creating Flutter apps.
108
109
00:09:32,740 --> 00:09:39,100
So we know that if we want something to happen the moment that our stateful widget is created and
109
110
00:09:39,130 --> 00:09:45,730
add into the tree, then we're going to put our code inside initState. If we want something to happen
110
111
00:09:45,940 --> 00:09:47,420
every single time
111
112
00:09:47,440 --> 00:09:52,180
our stateful widget gets rebuilt, then we'll put it into the build method.
112
113
00:09:52,180 --> 00:09:58,120
And finally if we want something to happen when our stateful widget gets destroyed, then we would put
113
114
00:09:58,120 --> 00:10:02,760
the code inside the deactivate method.
114
115
00:10:03,000 --> 00:10:08,800
So now using what we've learned on lifecycle methods, here's a challenge for you.
115
116
00:10:08,850 --> 00:10:17,340
I want you to change our code so that the position gets printed into the console without tapping on
116
117
00:10:17,340 --> 00:10:18,250
any buttons.
117
118
00:10:18,270 --> 00:10:24,140
In fact you can go ahead and delete the entire contents of the scaffold.
118
119
00:10:24,210 --> 00:10:27,330
What should happen is as soon as our app runs
119
120
00:10:27,480 --> 00:10:35,430
and as soon as this loading screen appears inside the phone then we should see our position being printed
120
121
00:10:35,430 --> 00:10:36,600
in the console.
121
122
00:10:36,870 --> 00:10:40,260
And this will rely on what you've learned from this lesson.
122
123
00:10:40,290 --> 00:10:45,470
Pause the video and try to complete that challenge all right.
123
124
00:10:45,500 --> 00:10:49,640
So currently when we run our app all we get is just the blank screen.
124
125
00:10:49,650 --> 00:10:54,020
There's nothing inside build, just a blank scaffold.
125
126
00:10:54,020 --> 00:10:58,910
So we're not gonna use any buttons to trigger getting the location.
126
127
00:10:58,910 --> 00:11:06,360
Instead we're going to add a initState to our loading screen. And because we know that this is going
127
128
00:11:06,360 --> 00:11:11,390
to be triggered as soon as our stateful widget gets created,
128
129
00:11:11,390 --> 00:11:15,330
so it's the moment that this appears on screen.
129
130
00:11:15,350 --> 00:11:21,380
Now it's important to know that initState only gets called once and it's only the moment when that
130
131
00:11:21,380 --> 00:11:24,180
state gets initialized and gets created.
131
132
00:11:24,290 --> 00:11:30,800
But something like build even though it does get called when our widget gets built onto the screen, but
132
133
00:11:30,800 --> 00:11:35,070
it gets caught every single time that our widgets rebuild.
133
134
00:11:35,090 --> 00:11:42,290
So every time a piece of text changes or an image changes or this animation, then build will be called again
134
135
00:11:42,290 --> 00:11:48,110
and again and again. And very often you don't want to put code in there that will get called repeatedly
135
136
00:11:48,470 --> 00:11:51,170
because it's very expensive.
136
137
00:11:51,170 --> 00:11:53,740
Instead we're going to put it inside initState.
137
138
00:11:53,780 --> 00:11:57,950
And so inside initState, we're going to call get location.
138
139
00:11:58,130 --> 00:12:05,840
And now if I go ahead and hot restart my app to make it reinitialize this particular stateful widget,
139
140
00:12:06,200 --> 00:12:11,720
then you can see as soon as it goes on the screen, I get my position printed in the console.
140
141
00:12:11,720 --> 00:12:19,940
I didn't have to press anything at all. So our lifecycle method are really useful if we want to tap in
141
142
00:12:19,940 --> 00:12:28,490
to a particular moment in the life of our stateful widgets. If we wanted to save a piece of data just
142
143
00:12:28,490 --> 00:12:34,670
before the stateful widget gets destroyed or if we want to deallocate something from memory or if we
143
144
00:12:34,670 --> 00:12:40,970
want to create a new object as soon as the stateful widget gets initialized, these are the methods that
144
145
00:12:40,970 --> 00:12:49,790
we can tap into to make our code run at a particular time. And in our case we're making our get location
145
146
00:12:49,790 --> 00:12:57,170
method run in the moment as soon as our loading screen state gets initialized which is going to be at
146
147
00:12:57,170 --> 00:13:02,240
the very start and we only make it run once. Now
147
148
00:13:02,240 --> 00:13:08,660
at the moment, we're getting our location and we're importing our geolocator all inside our loading
148
149
00:13:08,660 --> 00:13:11,170
screen which is kind of not its job right?
149
150
00:13:11,660 --> 00:13:17,570
So in the next lesson we're going to learn more about checking to see if the user has given permission
150
151
00:13:17,570 --> 00:13:19,030
to get the location.
151
152
00:13:19,160 --> 00:13:26,010
And we're also going to refactor all of the location related work into our location.dart file.
152
153
00:13:26,060 --> 00:13:29,240
So for all of that and more, I'll see on the next lesson.
17639
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.