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.