1
00:00:00,003 --> 00:00:03,086
(upbeat intro music)

2
00:00:04,849 --> 00:00:06,628
So this part we are now ready to create

3
00:00:06,628 --> 00:00:08,216
the ViewModel for our app.

4
00:00:08,216 --> 00:00:11,127
We want to start here by adding the necessary dependency

5
00:00:11,127 --> 00:00:13,277
to the build.grade file.

6
00:00:13,277 --> 00:00:16,328
so lets open our build.grade file,

7
00:00:16,328 --> 00:00:19,915
the module app, grade file is what we want.

8
00:00:19,915 --> 00:00:23,055
And what we want to do is add those dependencies.

9
00:00:23,055 --> 00:00:24,701
As we did for the Calculator app,

10
00:00:24,701 --> 00:00:27,639
you can copy and paste those same entries

11
00:00:27,639 --> 00:00:28,781
that you did last time.

12
00:00:28,781 --> 00:00:31,644
We got those from one of the Android support pages.

13
00:00:31,644 --> 00:00:33,447
I'm just gonna drop it in here.

14
00:00:33,447 --> 00:00:34,569
So either way will work.

15
00:00:34,569 --> 00:00:36,652
So def life cycle_version

16
00:00:38,877 --> 00:00:42,296
is equal to point type a quote "1.1.1"

17
00:00:42,296 --> 00:00:45,737
Then on the next line we're going to add a message there.

18
00:00:45,737 --> 00:00:49,458
The comment should say ViewModel and LiveData

19
00:00:49,458 --> 00:00:52,653
which is what this next line is going to be all about.

20
00:00:52,653 --> 00:00:56,026
We'll type implementation and double quotes.

21
00:00:56,026 --> 00:00:58,609
Android.arch, A R C H.lifecycle

22
00:01:00,851 --> 00:01:02,184
colon extensions

23
00:01:03,827 --> 00:01:06,060
colon and a dollar sign

24
00:01:06,060 --> 00:01:07,231
it's gonna be lifecycle

25
00:01:07,231 --> 00:01:08,825
in this version which is our variable,

26
00:01:08,825 --> 00:01:12,017
we've defined in the previous line.

27
00:01:12,017 --> 00:01:13,810
And closing double quote.

28
00:01:13,810 --> 00:01:14,988
The other entry we needed to change,

29
00:01:14,988 --> 00:01:17,625
which again we needed to do for the Calculator app,

30
00:01:17,625 --> 00:01:19,708
is change J R E to J D K.

31
00:01:21,198 --> 00:01:23,043
Let's go ahead and do that.

32
00:01:23,043 --> 00:01:25,415
And at that point we can now sync.

33
00:01:25,415 --> 00:01:27,140
It goes without saying, that it's important

34
00:01:27,140 --> 00:01:28,949
to type this exactly correct.

35
00:01:28,949 --> 00:01:32,315
If you don't type that line correctly you get an error

36
00:01:32,315 --> 00:01:33,972
when we go to uh, to sync.

37
00:01:33,972 --> 00:01:35,562
But in my case I've been able to sync it,

38
00:01:35,562 --> 00:01:37,489
so we're good to go.

39
00:01:37,489 --> 00:01:38,548
Alright, so let's have a think about

40
00:01:38,548 --> 00:01:42,119
how this ViewModel will fit into the overall structure

41
00:01:42,119 --> 00:01:43,412
of our app.

42
00:01:43,412 --> 00:01:46,019
Hopefully by now you've reviewed the Google document

43
00:01:46,019 --> 00:01:48,329
that we looked at in an earlier video.

44
00:01:48,329 --> 00:01:50,457
There's actual a diagram showing the lifecycle

45
00:01:50,457 --> 00:01:52,404
of a ViewModel in that.

46
00:01:52,404 --> 00:01:54,088
Let's just bring that up on screen.

47
00:01:54,088 --> 00:01:56,588
It is worth checking that out.

48
00:02:00,089 --> 00:02:01,030
And we'll just come down here

49
00:02:01,030 --> 00:02:03,469
to the lifecycle of a ViewModel,

50
00:02:03,469 --> 00:02:04,636
click on that.

51
00:02:05,924 --> 00:02:09,466
And there we can see the diagram that I'm talking about.

52
00:02:09,466 --> 00:02:11,471
So that diagram shows the activity

53
00:02:11,471 --> 00:02:14,064
being destroyed and recreated as a result

54
00:02:14,064 --> 00:02:15,918
of a configuration change.

55
00:02:15,918 --> 00:02:17,203
But the ViewModel exists

56
00:02:17,203 --> 00:02:20,068
until the activity is finally destroyed.

57
00:02:20,068 --> 00:02:21,949
If we make the ViewModel responsible

58
00:02:21,949 --> 00:02:23,510
for downloading the data

59
00:02:23,510 --> 00:02:24,886
then the data remains available

60
00:02:24,886 --> 00:02:26,856
after our configuration change.

61
00:02:26,856 --> 00:02:28,960
There's no need to download it again.

62
00:02:28,960 --> 00:02:31,103
And in our case that's exactly what we want.

63
00:02:31,103 --> 00:02:33,277
So let's actually see how a ViewModel

64
00:02:33,277 --> 00:02:35,194
will fit into this app.

65
00:02:36,486 --> 00:02:37,389
So as you can see in this slide,

66
00:02:37,389 --> 00:02:39,578
the ViewModel is gonna be responsible

67
00:02:39,578 --> 00:02:41,608
for keeping the feed data.

68
00:02:41,608 --> 00:02:45,141
So exposes this said data, for a LiveData object.

69
00:02:45,141 --> 00:02:47,775
Remember that LiveData can store any type of object

70
00:02:47,775 --> 00:02:51,423
we've used simple Strings and Doubles in the Calculator app,

71
00:02:51,423 --> 00:02:53,999
but here we're going to be using a LiveData object

72
00:02:53,999 --> 00:02:56,402
to hold an ArrayList.

73
00:02:56,402 --> 00:02:59,693
So when the ViewModel needs to get data from a new URL

74
00:02:59,693 --> 00:03:01,821
it creates a new DownloadData object

75
00:03:01,821 --> 00:03:03,964
and provides it with the URL

76
00:03:03,964 --> 00:03:05,901
to download from.

77
00:03:05,901 --> 00:03:08,221
So once DownloadData has finished downloading

78
00:03:08,221 --> 00:03:10,834
it creates a ParseApplications object

79
00:03:10,834 --> 00:03:12,540
to parse the data.

80
00:03:12,540 --> 00:03:15,093
We've discussed the fact that this isn't the best design

81
00:03:15,093 --> 00:03:17,872
and then we went and changed the way it worked

82
00:03:17,872 --> 00:03:19,512
in the Flickr Browser app.

83
00:03:19,512 --> 00:03:22,408
So it would be easy to separate these two classes

84
00:03:22,408 --> 00:03:24,850
so the DownloadData sends the raw data

85
00:03:24,850 --> 00:03:26,002
to the ViewModel.

86
00:03:26,002 --> 00:03:28,472
Then the ViewModel uses ParseApplications

87
00:03:28,472 --> 00:03:30,186
to preform the parsing.

88
00:03:30,186 --> 00:03:32,573
But we're really focusing on the ViewModel at this point.

89
00:03:32,573 --> 00:03:36,442
So we're not making any other changes at this time.

90
00:03:36,442 --> 00:03:38,243
DownloadData then calls the Viewodel's

91
00:03:38,243 --> 00:03:39,814
onDataAvailable function,

92
00:03:39,814 --> 00:03:43,891
and passes the list of feeds as an argument.

93
00:03:43,891 --> 00:03:45,671
The ViewModel now has an up to date list

94
00:03:45,671 --> 00:03:47,016
of the feed data,

95
00:03:47,016 --> 00:03:50,724
and exposes it through it's LiveData object.

96
00:03:50,724 --> 00:03:53,641
That's "feedEntries" in this diagram

97
00:03:53,641 --> 00:03:56,491
MainActivity observes this LiveData,

98
00:03:56,491 --> 00:03:58,534
and can respond whenever it changes.

99
00:03:58,534 --> 00:04:01,401
And in this case it responds by

100
00:04:01,401 --> 00:04:04,199
updating it's applica- it's adapter rather,

101
00:04:04,199 --> 00:04:06,371
with the new list.

102
00:04:06,371 --> 00:04:09,267
Now we'll need to make a small change to the Adapter.

103
00:04:09,267 --> 00:04:10,985
It'll need to provide a function

104
00:04:10,985 --> 00:04:14,471
that MainActivity can call, to provide the adapter

105
00:04:14,471 --> 00:04:15,628
with a new list.

106
00:04:15,628 --> 00:04:17,961
You'll also need to notify the ListView

107
00:04:17,961 --> 00:04:20,332
that its data has changed.

108
00:04:20,332 --> 00:04:22,440
We'll make both these changes once we've written

109
00:04:22,440 --> 00:04:24,356
our ViewModel class.

110
00:04:24,356 --> 00:04:25,979
Alright, so that's how it all fits together.

111
00:04:25,979 --> 00:04:28,338
So let's swing back now to Android Studio

112
00:04:28,338 --> 00:04:31,985
and create a new class, in fact we'll create our ViewModel.

113
00:04:31,985 --> 00:04:35,565
So I'm gonna go over, and under the top 10 download package,

114
00:04:35,565 --> 00:04:37,342
new Kotlin File Class

115
00:04:37,342 --> 00:04:40,925
and we're gonna call this one FeedViewModel

116
00:04:43,119 --> 00:04:45,793
I'm going to select Kind of Class

117
00:04:45,793 --> 00:04:48,286
started with a topping, press enter there.

118
00:04:48,286 --> 00:04:51,721
And I'm gonna start off by adding the usual tag that we had.

119
00:04:51,721 --> 00:04:53,971
That's private, const, val,

120
00:04:55,543 --> 00:04:57,543
TAG = FeedViewModel

121
00:05:01,272 --> 00:05:04,350
and for FeedViewModel we need to extend ViewModel

122
00:05:04,350 --> 00:05:07,002
and we also need to implement the down loader

123
00:05:07,002 --> 00:05:09,536
class is Downloader call back interface.

124
00:05:09,536 --> 00:05:10,691
So let's do that.

125
00:05:10,691 --> 00:05:14,096
So that's gonna be colon after the class definition.

126
00:05:14,096 --> 00:05:16,846
And ViewModel Parenthesis, comma,

127
00:05:18,779 --> 00:05:20,483
and download data,

128
00:05:20,483 --> 00:05:22,066
.DownloaderCallBack

129
00:05:23,292 --> 00:05:25,245
so I've got an error at the moment as usual

130
00:05:25,245 --> 00:05:27,161
because we haven't yet, implemented

131
00:05:27,161 --> 00:05:28,666
the interface function yet.

132
00:05:28,666 --> 00:05:30,414
But we'll fix that in a moment.

133
00:05:30,414 --> 00:05:32,861
First though we need to move some variables,

134
00:05:32,861 --> 00:05:35,528
from MainActivity into here.

135
00:05:35,528 --> 00:05:36,782
Let's go and check out MainActivity,

136
00:05:36,782 --> 00:05:38,743
and I'll just close down some of these other classes

137
00:05:38,743 --> 00:05:42,026
or at least the greater file of it.

138
00:05:42,026 --> 00:05:43,630
So I'm looking at our MainActivity class

139
00:05:43,630 --> 00:05:45,226
to finish it down here.

140
00:05:45,226 --> 00:05:46,936
We want the DownloadData field,

141
00:05:46,936 --> 00:05:48,387
that's obvious because MainActivity

142
00:05:48,387 --> 00:05:50,371
is no longer responsible for downloading.

143
00:05:50,371 --> 00:05:53,231
But we also want the feedChachedUrl variable

144
00:05:53,231 --> 00:05:55,661
our ViewModel will decide if the feed needs

145
00:05:55,661 --> 00:05:56,816
to be downloaded again.

146
00:05:56,816 --> 00:06:01,354
All MainActivity is going to do is request the feed.

147
00:06:01,354 --> 00:06:03,721
So let's actually take a copy of this

148
00:06:03,721 --> 00:06:06,335
select all of the feedCachedUrl

149
00:06:06,335 --> 00:06:08,709
I'm gonna cut that and paste that

150
00:06:08,709 --> 00:06:10,884
after the DownloadData definition

151
00:06:10,884 --> 00:06:13,811
so I can actually copy both of those lines.

152
00:06:13,811 --> 00:06:15,383
And before I do that though, you might be tempted

153
00:06:15,383 --> 00:06:19,548
to move feedUrl and feedLimit into the ViewModel as well.

154
00:06:19,548 --> 00:06:21,997
In this case that's not a good idea.

155
00:06:21,997 --> 00:06:24,374
The URL that the user's selected

156
00:06:24,374 --> 00:06:26,663
is part of the interaction with the UI

157
00:06:26,663 --> 00:06:28,586
so our responsibility for building the URL

158
00:06:28,586 --> 00:06:30,258
belongs to MainActivity.

159
00:06:30,258 --> 00:06:31,428
So I'm gonna copy those up,

160
00:06:31,428 --> 00:06:34,194
or probably should save those two lines

161
00:06:34,194 --> 00:06:37,334
that's the private var downloadData and the freeCachedUrl

162
00:06:37,334 --> 00:06:38,925
cut those out of MainActivity

163
00:06:38,925 --> 00:06:41,529
and go back to our FeedViewModel

164
00:06:41,529 --> 00:06:45,708
and paste them in there within our class definition.

165
00:06:45,708 --> 00:06:46,729
And looking back at MainActivity,

166
00:06:46,729 --> 00:06:49,417
we've now got arrows there or more arrows.

167
00:06:49,417 --> 00:06:51,074
But don't worry, that'll become right

168
00:06:51,074 --> 00:06:53,810
as we work on converting the app to user ViewModel.

169
00:06:53,810 --> 00:06:55,661
Alright so back to FeedViewModel

170
00:06:55,661 --> 00:06:58,156
we've pasted those two entries in there.

171
00:06:58,156 --> 00:07:00,574
So the ViewModel has to expose its data,

172
00:07:00,574 --> 00:07:02,641
and we're gonna use the same technique that we used

173
00:07:02,641 --> 00:07:04,722
at the end of the calculator conversion.

174
00:07:04,722 --> 00:07:07,099
So I have a private MutableLiveData object

175
00:07:07,099 --> 00:07:10,605
and expose the LiveData, to the ViewModel's own.

176
00:07:10,605 --> 00:07:11,447
Let's go ahead and do that.

177
00:07:11,447 --> 00:07:13,780
So it's going to be private,

178
00:07:15,007 --> 00:07:16,257
val feed equals

179
00:07:17,368 --> 00:07:19,785
it's gonna be MutableLiveData

180
00:07:21,032 --> 00:07:22,493
and the type there is going to be,

181
00:07:22,493 --> 00:07:25,601
a list of our FeedEntry objects.

182
00:07:25,601 --> 00:07:27,213
To list FeedEntry, I need to have parenthesis

183
00:07:27,213 --> 00:07:29,462
on the end of that.

184
00:07:29,462 --> 00:07:31,374
And on the next line, we're going to define

185
00:07:31,374 --> 00:07:33,351
our LiveData objects.

186
00:07:33,351 --> 00:07:34,934
So val feedEntries,

187
00:07:36,519 --> 00:07:37,686
colon LiveData

188
00:07:38,899 --> 00:07:42,714
and the definition, begin as a list of FeedEntry objects.

189
00:07:42,714 --> 00:07:44,354
List of FeedEntry.

190
00:07:44,354 --> 00:07:47,159
Then we need to find our get function,

191
00:07:47,159 --> 00:07:48,742
so get = feed.

192
00:07:50,966 --> 00:07:53,012
FeedViewModel will update feed,

193
00:07:53,012 --> 00:07:56,486
and MainActivity will be observing feedEntries.

194
00:07:56,486 --> 00:07:58,516
Now there's a minor problem with LiveData,

195
00:07:58,516 --> 00:08:01,060
it's not one I can see Google changing,

196
00:08:01,060 --> 00:08:03,236
at least not in the short term anyway.

197
00:08:03,236 --> 00:08:05,674
We've declared our LiveData and MutableLiveData objects,

198
00:08:05,674 --> 00:08:08,516
as storing a list of feedEntry objects.

199
00:08:08,516 --> 00:08:11,518
Unfortunately though, that will hold the server till now

200
00:08:11,518 --> 00:08:13,494
until we initialise it with something,

201
00:08:13,494 --> 00:08:16,253
there's not really anything else we can return.

202
00:08:16,253 --> 00:08:18,275
So we're gonna make sure we don't get any errors,

203
00:08:18,275 --> 00:08:20,266
as a result of returning now,

204
00:08:20,266 --> 00:08:23,671
by initialising the MutableLiveData object straight away.

205
00:08:23,671 --> 00:08:26,277
So I'm gonna add a nit block to actually do that.

206
00:08:26,277 --> 00:08:29,454
So I'll add that just below the definitions there in it.

207
00:08:29,454 --> 00:08:33,421
Left to right curly braces, and we're gonna type

208
00:08:33,421 --> 00:08:34,754
feed.post value,

209
00:08:35,913 --> 00:08:38,461
then in parenthesis, EMPTY capitalised

210
00:08:38,461 --> 00:08:39,544
_FEED, _LIST.

211
00:08:40,792 --> 00:08:43,224
Closing in our right parenthesis there.

212
00:08:43,224 --> 00:08:44,390
So that's worth doing, but you'll still see the

213
00:08:44,390 --> 00:08:46,776
compiler complaining, we'll deal with that

214
00:08:46,776 --> 00:08:47,856
when we come to it.

215
00:08:47,856 --> 00:08:51,319
But what's this EMPTY_FEED_LIST?

216
00:08:51,319 --> 00:08:53,105
Well the Java Collections class provides

217
00:08:53,105 --> 00:08:54,883
and empty list for situations like this.

218
00:08:54,883 --> 00:08:57,496
Rather than creating a new ArrayList

219
00:08:57,496 --> 00:08:58,920
we can actually use the empty list

220
00:08:58,920 --> 00:09:01,370
that Collections provides for us.

221
00:09:01,370 --> 00:09:03,123
That's a bit more efficient than creating objects

222
00:09:03,123 --> 00:09:04,704
that we are not going to use.

223
00:09:04,704 --> 00:09:07,486
Another advantage is this empty list is immutable.

224
00:09:07,486 --> 00:09:09,119
Now if for some strange reason,

225
00:09:09,119 --> 00:09:11,688
our code tries to add items to it

226
00:09:11,688 --> 00:09:12,995
we'd get an error.

227
00:09:12,995 --> 00:09:15,527
So you see the empty list from the Collections class

228
00:09:15,527 --> 00:09:18,110
makes that code a bit more robust.

229
00:09:18,110 --> 00:09:22,329
You can't actually mark EMPTY_FEED_LIST as a constant,

230
00:09:22,329 --> 00:09:24,267
but that's effectively what it is here.

231
00:09:24,267 --> 00:09:25,454
What we can do though

232
00:09:25,454 --> 00:09:27,626
is put the definition at the top of the file,

233
00:09:27,626 --> 00:09:30,331
so that it's available in other parts of the project.

234
00:09:30,331 --> 00:09:31,182
Let's go ahead and do that.

235
00:09:31,182 --> 00:09:32,968
So we're gonna do that just below

236
00:09:32,968 --> 00:09:35,801
the TAG definition online, its 11.

237
00:09:37,133 --> 00:09:42,133
So that's gonna be val, and in uppercase EMPTY_FEED_LIST.

238
00:09:42,363 --> 00:09:43,724
And it's a list of FeedEntry objects,

239
00:09:43,724 --> 00:09:48,384
so list FeedEntry objects, and it's gonna be equal

240
00:09:48,384 --> 00:09:50,467
to Collections.emptyList.

241
00:09:52,479 --> 00:09:55,079
You can see the arrow disappears on line 26.

242
00:09:55,079 --> 00:09:57,381
And just out of interest, if you click on this emptyList

243
00:09:57,381 --> 00:10:01,158
method call there, because it's Java source code.

244
00:10:01,158 --> 00:10:02,922
You'll see that it's a top side version

245
00:10:02,922 --> 00:10:05,560
of the empty, and it's called list constant.

246
00:10:05,560 --> 00:10:07,969
So it's been cast to top we want,

247
00:10:07,969 --> 00:10:10,393
which in this case is a list of FeedEntry objects.

248
00:10:10,393 --> 00:10:12,371
Just above the doc stream for the method,

249
00:10:12,371 --> 00:10:16,086
there's a definition of EMPTY underscore LIST there.

250
00:10:16,086 --> 00:10:19,278
You can see there on line 4,443.

251
00:10:19,278 --> 00:10:20,236
And that's effectively the object

252
00:10:20,236 --> 00:10:21,727
that we're gonna be getting here.

253
00:10:21,727 --> 00:10:23,916
That's a public static final object

254
00:10:23,916 --> 00:10:27,840
which is the Java equivalent of a public const in Kotlin.

255
00:10:27,840 --> 00:10:29,901
Now let's just close down that Java source.

256
00:10:29,901 --> 00:10:31,906
Back to our FeedViewModel.

257
00:10:31,906 --> 00:10:34,330
So the next bit of our code, we need to list

258
00:10:34,330 --> 00:10:37,587
our MainActivity as the download URL function.

259
00:10:37,587 --> 00:10:39,692
So let's go and grab that.

260
00:10:39,692 --> 00:10:44,053
So I'm going to cut that out of the MainActivity class

261
00:10:44,053 --> 00:10:47,595
and we'll paste that directly in to our FeedViewModel.

262
00:10:47,595 --> 00:10:51,220
We'll paste it right in there below the init.

263
00:10:51,220 --> 00:10:54,397
Now this situation, I'm gonna suggest you accept the imports

264
00:10:54,397 --> 00:10:56,183
even though you can see that one of them there

265
00:10:56,183 --> 00:10:57,710
is a synthetic import.

266
00:10:57,710 --> 00:10:59,377
We'll fix that next.

267
00:11:00,810 --> 00:11:03,120
Let's clean up some of these empty spaces.

268
00:11:03,120 --> 00:11:05,507
So we need to make a few changes to this function.

269
00:11:05,507 --> 00:11:08,410
Now the function was private in MainActivity.

270
00:11:08,410 --> 00:11:10,014
But we need to make it available

271
00:11:10,014 --> 00:11:11,799
to our ViewModel's owner.

272
00:11:11,799 --> 00:11:13,456
And also take the opportunity

273
00:11:13,456 --> 00:11:15,352
to where the logging line one's called.

274
00:11:15,352 --> 00:11:17,229
And the last thing we want to do is make a change

275
00:11:17,229 --> 00:11:19,152
to remove the X in the list view

276
00:11:19,152 --> 00:11:21,646
from the DownloadData constructor.

277
00:11:21,646 --> 00:11:23,689
So let's remove the private there,

278
00:11:23,689 --> 00:11:26,744
so the ViewModel owner can access this.

279
00:11:26,744 --> 00:11:29,245
Gonna add some logging as I mentioned.

280
00:11:29,245 --> 00:11:31,622
Log.D parenthesis, TAG, comma

281
00:11:31,622 --> 00:11:33,872
We'll just put downloadUrl,

282
00:11:34,733 --> 00:11:37,233
and called with url $ feedUrl.

283
00:11:41,218 --> 00:11:43,750
And as I mentioned we need to remove the second argument

284
00:11:43,750 --> 00:11:46,583
from the DownloadData constructor.

285
00:11:47,777 --> 00:11:49,761
And you will often have to tweak functions slightly,

286
00:11:49,761 --> 00:11:52,808
like we're doing here when you move them into a ViewModel.

287
00:11:52,808 --> 00:11:55,097
The changes we make here are quite trivial.

288
00:11:55,097 --> 00:11:56,707
The only ones we had to make,

289
00:11:56,707 --> 00:11:58,698
were to remove private and delete the reference

290
00:11:58,698 --> 00:11:59,531
to the ListView.

291
00:11:59,531 --> 00:12:01,117
We checked the X in the ListView,

292
00:12:01,117 --> 00:12:02,513
that's a UI component,

293
00:12:02,513 --> 00:12:04,726
and that doesn't belong to the ViewModel.

294
00:12:04,726 --> 00:12:07,797
So Android Studio should have removed that synthetic import

295
00:12:07,797 --> 00:12:09,574
but if you go up and have a look there

296
00:12:09,574 --> 00:12:10,822
if not you can delete it now

297
00:12:10,822 --> 00:12:13,238
and you can see we also got the X in the ListView there.

298
00:12:13,238 --> 00:12:15,008
They're greyed out now, because they are no longer in use.

299
00:12:15,008 --> 00:12:18,002
I'm going to remove those manually.

300
00:12:18,002 --> 00:12:19,444
But you might find Android Studio's done

301
00:12:19,444 --> 00:12:21,130
that for you automatically.

302
00:12:21,130 --> 00:12:23,175
So the DownloadUrl function at this point

303
00:12:23,175 --> 00:12:25,417
is doing exactly what it did before

304
00:12:25,417 --> 00:12:27,881
including checking, to see if it's necessary

305
00:12:27,881 --> 00:12:29,614
to download the dollar again.

306
00:12:29,614 --> 00:12:32,076
If the URL hasn't changed, then there's no need

307
00:12:32,076 --> 00:12:33,733
to perform another download.

308
00:12:33,733 --> 00:12:37,240
However we did provide the users with a refresh menu item

309
00:12:37,240 --> 00:12:39,073
and we need some way to indicate

310
00:12:39,073 --> 00:12:41,602
that the download should be performed again.

311
00:12:41,602 --> 00:12:44,728
And we can do that by invalidating the FeedCacheUrl.

312
00:12:44,728 --> 00:12:46,705
So to do that, I'm gonna add a function

313
00:12:46,705 --> 00:12:48,205
after downloadUrl.

314
00:12:49,692 --> 00:12:53,359
So fun invalidate we'll call it, parenthesis

315
00:12:54,474 --> 00:12:57,141
and we'll just type feedCacheUrl

316
00:12:58,478 --> 00:13:01,395
and set that equal to "INVALIDATE".

317
00:13:02,742 --> 00:13:05,197
Below that,let's actually get Android Studio

318
00:13:05,197 --> 00:13:08,138
to generate the required onDataAvailable function

319
00:13:08,138 --> 00:13:09,638
for our interface.

320
00:13:11,519 --> 00:13:12,852
OnDataAvailable.

321
00:13:13,921 --> 00:13:16,679
And let's actually add some Logging first

322
00:13:16,679 --> 00:13:19,615
our Log.d will override the to do.

323
00:13:19,615 --> 00:13:21,948
TAG, onDataAvailable called,

324
00:13:25,792 --> 00:13:29,042
then we'll type feed.value = data.

325
00:13:30,138 --> 00:13:32,547
Valueing what's past of this function.

326
00:13:32,547 --> 00:13:35,815
We'll do Log.d parenthesis, TAG, comma,

327
00:13:35,815 --> 00:13:37,565
onDataAvailable ends.

328
00:13:43,336 --> 00:13:44,522
So our only work down there is

329
00:13:44,522 --> 00:13:48,056
to assign the data to the MutableLiveData object.

330
00:13:48,056 --> 00:13:49,234
So the final change now is

331
00:13:49,234 --> 00:13:51,484
to do something that MainActivity's currently doing.

332
00:13:51,484 --> 00:13:54,198
We've still got a few arrows in MainActivity

333
00:13:54,198 --> 00:13:56,241
you can see here.

334
00:13:56,241 --> 00:13:58,240
And we're gonna fix those in the next video,

335
00:13:58,240 --> 00:14:01,098
when we get this modified app up and actually running.

336
00:14:01,098 --> 00:14:02,764
And there aren't really many changes to make

337
00:14:02,764 --> 00:14:03,742
as you can see there.

338
00:14:03,742 --> 00:14:05,773
But one that we will make right now

339
00:14:05,773 --> 00:14:07,162
is right at the end of MainActivity.

340
00:14:07,162 --> 00:14:08,568
If you go right down to the bottom there,

341
00:14:08,568 --> 00:14:11,137
we got this onDestroy function.

342
00:14:11,137 --> 00:14:13,052
So this onDestroy function's cancelling

343
00:14:13,052 --> 00:14:14,981
any download that may be going on.

344
00:14:14,981 --> 00:14:17,246
MainActivity no longer knows about downloading.

345
00:14:17,246 --> 00:14:19,792
So therefore it shouldn't be tempting to cancel it.

346
00:14:19,792 --> 00:14:21,923
We can delete that function from here.

347
00:14:21,923 --> 00:14:24,090
So we're going to do that.

348
00:14:25,986 --> 00:14:28,251
Now this is an extremely important change

349
00:14:28,251 --> 00:14:30,228
it really highlights one of the advantages

350
00:14:30,228 --> 00:14:31,276
of using a ViewModel.

351
00:14:31,276 --> 00:14:33,451
With this function in MainActivity,

352
00:14:33,451 --> 00:14:36,216
consider what happens if the user starts a download

353
00:14:36,216 --> 00:14:37,903
then rotates the device.

354
00:14:37,903 --> 00:14:39,628
When the activity gets destroyed,

355
00:14:39,628 --> 00:14:41,976
this function will cancel the download.

356
00:14:41,976 --> 00:14:44,827
It may have nearly finished, but it will still be cancelled.

357
00:14:44,827 --> 00:14:46,530
When the activity is recreated,

358
00:14:46,530 --> 00:14:48,747
the download will start again.

359
00:14:48,747 --> 00:14:50,540
But now that we've deleted that function,

360
00:14:50,540 --> 00:14:52,993
instead will cancel any pending download

361
00:14:52,993 --> 00:14:56,130
in the ViewModel using its onCleared function.

362
00:14:56,130 --> 00:14:58,607
And I'll get Android Studio to generate the function.

363
00:14:58,607 --> 00:15:00,690
Just go back to that now.

364
00:15:02,871 --> 00:15:05,530
So implement the onCleared function.

365
00:15:05,530 --> 00:15:08,498
You can see that's on the ViewModel there.

366
00:15:08,498 --> 00:15:10,557
And we'll start by removing the super,

367
00:15:10,557 --> 00:15:13,640
with a Log.d, parenthesis, TAG comma,

368
00:15:15,102 --> 00:15:17,013
onCleared colon

369
00:15:17,013 --> 00:15:19,346
cancelling pending downloads.

370
00:15:22,344 --> 00:15:26,858
Then we'll put downloadData code operator .cancel

371
00:15:26,858 --> 00:15:28,275
parenthesis true.

372
00:15:29,399 --> 00:15:31,122
So remember from the ViewModel lifecycle,

373
00:15:31,122 --> 00:15:32,642
that onCleared's called

374
00:15:32,642 --> 00:15:35,424
when the ViewModel's no longer used.

375
00:15:35,424 --> 00:15:37,582
It's a good place to tidy up any resources,

376
00:15:37,582 --> 00:15:41,245
such as any acing tasks, for example that is selected.

377
00:15:41,245 --> 00:15:44,281
And because the ViewModel survives the configuration change,

378
00:15:44,281 --> 00:15:46,309
the download won't be cancelled

379
00:15:46,309 --> 00:15:48,024
when the user rotates the device.

380
00:15:48,024 --> 00:15:50,487
That's a huge improvement.

381
00:15:50,487 --> 00:15:52,661
Alright so that's our ViewModel finished.

382
00:15:52,661 --> 00:15:53,944
The next video we'll start the process

383
00:15:53,944 --> 00:15:56,453
of modifying MainActivity, and run the app

384
00:15:56,453 --> 00:15:58,705
and check out what we need to do to finish it off.

385
00:15:58,705 --> 00:16:01,133
So I'll see you in the next video.

