1 00:00:04,740 --> 00:00:06,750 now that we've seen how to use a view 2 00:00:06,750 --> 00:00:09,000 model and live data in a very simple app 3 00:00:09,000 --> 00:00:10,860 it's time to look at something a bit 4 00:00:10,860 --> 00:00:13,260 more complex when we finished the top to 5 00:00:13,260 --> 00:00:15,510 him downloader app it still had one 6 00:00:15,510 --> 00:00:18,449 floor we tried to avoid unnecessary yard 7 00:00:18,449 --> 00:00:21,300 downloads as much as possible but the 8 00:00:21,300 --> 00:00:23,039 app still downloaded the data again 9 00:00:23,039 --> 00:00:25,170 after a configuration change such as 10 00:00:25,170 --> 00:00:28,020 rotating the device at the time I 11 00:00:28,020 --> 00:00:30,000 suggested that you could use a loader to 12 00:00:30,000 --> 00:00:31,710 prevent this and said that would be 13 00:00:31,710 --> 00:00:33,270 covering loaders later in the course 14 00:00:33,270 --> 00:00:37,500 however in June 2018 Google deprecated 15 00:00:37,500 --> 00:00:39,420 the loader classes so we're now going to 16 00:00:39,420 --> 00:00:42,000 be using the view model plus instead 17 00:00:42,000 --> 00:00:44,460 we've seen that a view model survives a 18 00:00:44,460 --> 00:00:46,590 configuration change which means it 19 00:00:46,590 --> 00:00:48,180 shouldn't have to download the data 20 00:00:48,180 --> 00:00:51,210 again when the device is rotated so in 21 00:00:51,210 --> 00:00:52,710 this video we'll start the process of 22 00:00:52,710 --> 00:00:55,079 changing the top 10 downloader to use a 23 00:00:55,079 --> 00:00:58,230 view model and solve this problem so 24 00:00:58,230 --> 00:01:00,210 start with the top 10 downloaded project 25 00:01:00,210 --> 00:01:01,860 open and you can see that I've got that 26 00:01:01,860 --> 00:01:04,379 open on screen you can download that so 27 00:01:04,379 --> 00:01:07,140 from the final video in section 7 where 28 00:01:07,140 --> 00:01:09,390 we created the top 10 download our app 29 00:01:09,390 --> 00:01:11,760 in this course if you need to so first 30 00:01:11,760 --> 00:01:13,890 thing I'm looking at main activity you 31 00:01:13,890 --> 00:01:15,270 can see it's got quite a bit of code 32 00:01:15,270 --> 00:01:17,490 that's concerned with the UI as we 33 00:01:17,490 --> 00:01:19,470 scroll down and check out so it needs to 34 00:01:19,470 --> 00:01:21,240 keep track of the feed limit that the 35 00:01:21,240 --> 00:01:23,880 user selected in order to make the menu 36 00:01:23,880 --> 00:01:26,670 correctly reflect their choice now 37 00:01:26,670 --> 00:01:28,560 because the feed limit is used to 38 00:01:28,560 --> 00:01:31,080 construct the URL it makes sense to 39 00:01:31,080 --> 00:01:33,840 leave responsibility for restoring feed 40 00:01:33,840 --> 00:01:36,420 URL with main activity as well you may 41 00:01:36,420 --> 00:01:38,100 decide to do things differently but I 42 00:01:38,100 --> 00:01:40,229 like the fact that the view model isn't 43 00:01:40,229 --> 00:01:41,960 going to know how to construct the gyro 44 00:01:41,960 --> 00:01:44,520 it'll be given a fully form link to the 45 00:01:44,520 --> 00:01:46,830 RSS feed and doesn't have to worry about 46 00:01:46,830 --> 00:01:48,540 formatting it with different feed limits 47 00:01:48,540 --> 00:01:51,180 so this separation of responsibilities 48 00:01:51,180 --> 00:01:53,729 makes it easier to make changes to your 49 00:01:53,729 --> 00:01:56,189 app without breaking things you could 50 00:01:56,189 --> 00:01:58,320 use a different feed for example and the 51 00:01:58,320 --> 00:02:00,299 view model would still work well so 52 00:02:00,299 --> 00:02:01,560 moving down a bit further 53 00:02:01,560 --> 00:02:03,810 most of the conveyor code in here is 54 00:02:03,810 --> 00:02:05,490 concerned as I mentioned with the gyro 55 00:02:05,490 --> 00:02:07,979 but looking down here we've got this 56 00:02:07,979 --> 00:02:10,439 function that download gyro well that 57 00:02:10,439 --> 00:02:11,670 shouldn't be in here because that's not 58 00:02:11,670 --> 00:02:14,189 a UI function and also scorned a little 59 00:02:14,189 --> 00:02:15,629 bit further we've looked towards the 60 00:02:15,629 --> 00:02:17,230 bottom of the class 61 00:02:17,230 --> 00:02:19,780 we've got this companion object and 62 00:02:19,780 --> 00:02:21,489 that's the downloaded companion object 63 00:02:21,489 --> 00:02:22,930 we shouldn't have that in this class 64 00:02:22,930 --> 00:02:25,390 either well that's a good place to start 65 00:02:25,390 --> 00:02:27,099 I think this download our companion 66 00:02:27,099 --> 00:02:28,930 object so what I'm going to do is create 67 00:02:28,930 --> 00:02:31,150 a new Copland file class let's go ahead 68 00:02:31,150 --> 00:02:33,970 and do that it's a new Kotlin file class 69 00:02:33,970 --> 00:02:37,270 we'll call this one download data now 70 00:02:37,270 --> 00:02:38,620 because we're going to be cutting all 71 00:02:38,620 --> 00:02:39,790 the code we've got all the code we need 72 00:02:39,790 --> 00:02:41,980 I won't bother selecting class from the 73 00:02:41,980 --> 00:02:44,950 drop-down so next we want to go back to 74 00:02:44,950 --> 00:02:46,360 main activity we're going to cut all the 75 00:02:46,360 --> 00:02:48,760 code out from the companion object from 76 00:02:48,760 --> 00:02:53,170 the Declaration right through down to 77 00:02:53,170 --> 00:02:55,690 the closing right tab curly brace 78 00:02:55,690 --> 00:02:58,120 leaving just the companion line there 79 00:02:58,120 --> 00:02:59,860 and I'm going to take the opportunity to 80 00:02:59,860 --> 00:03:01,030 delete that as well cuz we won't be 81 00:03:01,030 --> 00:03:03,040 needing that anymore I'm going to paste 82 00:03:03,040 --> 00:03:06,040 that in the download data class that we 83 00:03:06,040 --> 00:03:08,319 just created and that's when I got to 84 00:03:08,319 --> 00:03:09,700 paste it we've got a lump of imports 85 00:03:09,700 --> 00:03:11,560 that I've actually popped up now in this 86 00:03:11,560 --> 00:03:13,569 case we don't want to import Android 87 00:03:13,569 --> 00:03:15,549 widgets on this view so I'm gonna 88 00:03:15,549 --> 00:03:17,530 unselect that one from the list and 89 00:03:17,530 --> 00:03:19,540 obviously that's a UI related thing 90 00:03:19,540 --> 00:03:21,430 which is why we're not including it okay 91 00:03:21,430 --> 00:03:24,190 okay we've got that you know paste it in 92 00:03:24,190 --> 00:03:27,340 to our downloaded data class this is a 93 00:03:27,340 --> 00:03:30,790 basic async class and we you shouldn't 94 00:03:30,790 --> 00:03:33,310 have to make too many changes to it what 95 00:03:33,310 --> 00:03:34,690 I'll do you I'll start off by doing is 96 00:03:34,690 --> 00:03:38,079 pasting or moving the tag to the top 97 00:03:38,079 --> 00:03:39,670 level and make it a costs let's go ahead 98 00:03:39,670 --> 00:03:45,579 and do that and that should be Const now 99 00:03:45,579 --> 00:03:47,350 also we won't need a context for the 100 00:03:47,350 --> 00:03:51,640 definition here or reference to the 101 00:03:51,640 --> 00:03:52,209 ListView 102 00:03:52,209 --> 00:03:53,950 in fact this class shouldn't have any 103 00:03:53,950 --> 00:03:55,870 knowledge about the UI it's just going 104 00:03:55,870 --> 00:03:58,600 to download and parse the data now it 105 00:03:58,600 --> 00:04:00,880 will need to know what created it to 106 00:04:00,880 --> 00:04:02,109 call it back when the data is available 107 00:04:02,109 --> 00:04:04,750 and it shouldn't be marked private so 108 00:04:04,750 --> 00:04:06,569 I'm going to delete that out for now 109 00:04:06,569 --> 00:04:08,530 change the definition so it's no longer 110 00:04:08,530 --> 00:04:11,109 private then within the parentheses 111 00:04:11,109 --> 00:04:12,819 we're going to be using an interface 112 00:04:12,819 --> 00:04:14,950 method to call back on and we'll write 113 00:04:14,950 --> 00:04:16,539 that after the declaration but let's in 114 00:04:16,539 --> 00:04:20,019 print parentheses add private val call 115 00:04:20,019 --> 00:04:21,548 back : 116 00:04:21,548 --> 00:04:24,570 I'll call it downloader call back 117 00:04:24,570 --> 00:04:27,340 leaving everything else s is callback 118 00:04:27,340 --> 00:04:29,110 will be the object that created the 119 00:04:29,110 --> 00:04:30,850 download data instance 120 00:04:30,850 --> 00:04:32,440 and we'll implement a function that we 121 00:04:32,440 --> 00:04:34,450 can call so we'll get to the interface 122 00:04:34,450 --> 00:04:37,240 shortly but what we can do now is remove 123 00:04:37,240 --> 00:04:39,760 the two var declarations up here because 124 00:04:39,760 --> 00:04:40,810 we're going to replace those in our 125 00:04:40,810 --> 00:04:43,450 interface with our interface we're also 126 00:04:43,450 --> 00:04:45,310 going to delete the init block there as 127 00:04:45,310 --> 00:04:49,870 well all right so I'll go ahead now and 128 00:04:49,870 --> 00:04:54,280 add our interface so interface and it's 129 00:04:54,280 --> 00:04:57,520 download a callback then add a left or 130 00:04:57,520 --> 00:04:59,440 right curly brace there's going to be 131 00:04:59,440 --> 00:05:01,870 fun we can add a function fun it's going 132 00:05:01,870 --> 00:05:06,670 to be on data available parentheses data 133 00:05:06,670 --> 00:05:09,220 : and we're going to find this a list of 134 00:05:09,220 --> 00:05:11,380 feed entry objects and lists and then a 135 00:05:11,380 --> 00:05:13,240 diamond and there's going to be feed 136 00:05:13,240 --> 00:05:17,970 entry alright so that's how it defines 137 00:05:17,970 --> 00:05:20,650 so we've now got errors in the on post 138 00:05:20,650 --> 00:05:23,110 execute function when we try to refer to 139 00:05:23,110 --> 00:05:24,760 things like the adapter in the list view 140 00:05:24,760 --> 00:05:26,890 again this class isn't concerned about 141 00:05:26,890 --> 00:05:28,600 the UI it's just you know it just 142 00:05:28,600 --> 00:05:31,300 downloads and passes the data and sends 143 00:05:31,300 --> 00:05:32,830 the result back so what I'm going to do 144 00:05:32,830 --> 00:05:35,590 is replace the code with a call to the 145 00:05:35,590 --> 00:05:38,170 calling classes on data available 146 00:05:38,170 --> 00:05:39,550 section let's go ahead and clean that up 147 00:05:39,550 --> 00:05:42,570 a bit so I'm going to delete this super 148 00:05:42,570 --> 00:05:45,460 and I believe the other tag entry that 149 00:05:45,460 --> 00:05:47,770 we had there what we're also going to do 150 00:05:47,770 --> 00:05:50,680 is only pass the data if result isn't an 151 00:05:50,680 --> 00:05:52,510 empty string so on the line after the 152 00:05:52,510 --> 00:05:54,610 VAR pars applications we'll do a test 153 00:05:54,610 --> 00:05:55,150 for that 154 00:05:55,150 --> 00:05:58,300 if parentheses result is not empty so 155 00:05:58,300 --> 00:06:01,210 dot is not empty closing your 156 00:06:01,210 --> 00:06:04,240 parentheses at a code block then and 157 00:06:04,240 --> 00:06:06,130 only then when we do a pause and stop 158 00:06:06,130 --> 00:06:10,090 pars result I could have just copied 159 00:06:10,090 --> 00:06:11,260 that line there so I'm going to delete 160 00:06:11,260 --> 00:06:13,480 that now again we're not concerned with 161 00:06:13,480 --> 00:06:15,220 the UI so we're going to delete these 162 00:06:15,220 --> 00:06:16,870 two lines here we don't want to want to 163 00:06:16,870 --> 00:06:19,570 be updating the user interface here 164 00:06:19,570 --> 00:06:20,830 instead what we're going to do is just 165 00:06:20,830 --> 00:06:22,750 add that callback as I mentioned so 166 00:06:22,750 --> 00:06:25,960 callback dot on data available we're 167 00:06:25,960 --> 00:06:27,580 going to parse applications or paths 168 00:06:27,580 --> 00:06:31,110 sparse applications dot applications 169 00:06:31,110 --> 00:06:33,640 looking further down there the doing 170 00:06:33,640 --> 00:06:35,590 background function is fine but that's 171 00:06:35,590 --> 00:06:37,300 been making quite a significant change 172 00:06:37,300 --> 00:06:39,250 to the app structure what I'm going to 173 00:06:39,250 --> 00:06:41,860 do is rename all the logging there it is 174 00:06:41,860 --> 00:06:43,150 useful to check that the function has 175 00:06:43,150 --> 00:06:44,770 been called 176 00:06:44,770 --> 00:06:47,500 I'll just move that back and at this 177 00:06:47,500 --> 00:06:49,660 point we're done with the modifications 178 00:06:49,660 --> 00:06:52,450 for this class but one thing I do want 179 00:06:52,450 --> 00:06:54,340 to show you and what we need to change 180 00:06:54,340 --> 00:06:56,620 is when we initially talked about and 181 00:06:56,620 --> 00:06:58,750 set up this download XML function or 182 00:06:58,750 --> 00:07:00,460 showing you how simple it was to do that 183 00:07:00,460 --> 00:07:02,950 I did leave out the error handling we 184 00:07:02,950 --> 00:07:04,480 had enough to concentrate on at the time 185 00:07:04,480 --> 00:07:06,640 but now is a good opportunity to add 186 00:07:06,640 --> 00:07:08,530 that back again so let's go ahead and do 187 00:07:08,530 --> 00:07:11,080 that this is the download XML function 188 00:07:11,080 --> 00:07:13,240 so I'm gonna start here by adding things 189 00:07:13,240 --> 00:07:14,830 to a try block here so it's gonna be try 190 00:07:14,830 --> 00:07:17,950 left curly brace and I'm gonna indent 191 00:07:17,950 --> 00:07:19,710 the return there they'll have a closing 192 00:07:19,710 --> 00:07:22,420 right curly brace then we need to catch 193 00:07:22,420 --> 00:07:24,790 some exceptions so we'll start with a 194 00:07:24,790 --> 00:07:27,670 catched ecole and we'll start with 195 00:07:27,670 --> 00:07:31,570 malformed at URL exception so if you get 196 00:07:31,570 --> 00:07:34,080 that we're gonna do a log d parentheses 197 00:07:34,080 --> 00:07:40,590 tag comma download XML colon invalid 198 00:07:40,590 --> 00:07:43,960 euro and closing double quote + 199 00:07:43,960 --> 00:07:47,380 e.message so that's our first one next 200 00:07:47,380 --> 00:07:49,750 what I'm going to do is annoy exception 201 00:07:49,750 --> 00:07:54,910 so catch e : hi our exception same do 202 00:07:54,910 --> 00:07:57,070 there with the log log D you could do 203 00:07:57,070 --> 00:07:59,140 and logged on either but for debug 204 00:07:59,140 --> 00:08:00,820 purposes I'm going to leave the log D in 205 00:08:00,820 --> 00:08:02,140 there because that'll become useful a 206 00:08:02,140 --> 00:08:05,740 few videos time so log D parenthesis tag 207 00:08:05,740 --> 00:08:11,710 comma and download XML again just home 208 00:08:11,710 --> 00:08:14,710 IO exception reading data is it getting 209 00:08:14,710 --> 00:08:16,960 the error message then we'll let our 210 00:08:16,960 --> 00:08:19,060 plus e dot message on the end again so 211 00:08:19,060 --> 00:08:20,260 you get more details about what the 212 00:08:20,260 --> 00:08:22,660 exception was I need to change that 213 00:08:22,660 --> 00:08:25,000 reference to a lock I see there and the 214 00:08:25,000 --> 00:08:26,530 third exception we want to catch is a 215 00:08:26,530 --> 00:08:29,710 security exception e : security 216 00:08:29,710 --> 00:08:33,750 exception log D parentheses ter comma 217 00:08:33,750 --> 00:08:38,320 there's gonna be download XML : security 218 00:08:38,320 --> 00:08:42,429 exception and we'll ask the question 219 00:08:42,429 --> 00:08:45,160 needs permission question mark then 220 00:08:45,160 --> 00:08:50,170 double quote + e dot message and what 221 00:08:50,170 --> 00:08:51,250 you could do there as you can do an e 222 00:08:51,250 --> 00:08:52,870 dot print stack trace if you wanted to 223 00:08:52,870 --> 00:08:54,940 and done uppercase e there again 224 00:08:54,940 --> 00:08:57,520 eat up print stack trace but I'll 225 00:08:57,520 --> 00:08:58,450 actually comment it out for 226 00:08:58,450 --> 00:09:00,310 now then one other thing we need to do 227 00:09:00,310 --> 00:09:01,930 here though because we haven't closed 228 00:09:01,930 --> 00:09:05,140 that in the Tri we need to return an 229 00:09:05,140 --> 00:09:06,550 empty string in fact if there was an 230 00:09:06,550 --> 00:09:08,290 exception so down here we little 231 00:09:08,290 --> 00:09:11,530 returned an empty string and we just 232 00:09:11,530 --> 00:09:14,110 make a quick note about that turn an 233 00:09:14,110 --> 00:09:17,350 empty string if there was an exception 234 00:09:17,350 --> 00:09:21,670 now what I would like to do is tidy up 235 00:09:21,670 --> 00:09:23,830 these nullable parameters in the two 236 00:09:23,830 --> 00:09:26,020 functions if we end up passing a null 237 00:09:26,020 --> 00:09:28,330 string for the URL that's an error in 238 00:09:28,330 --> 00:09:30,370 our code so I'd rather the app pressures 239 00:09:30,370 --> 00:09:32,350 quickly so that we can detect the 240 00:09:32,350 --> 00:09:34,150 problem in testing so for the doing 241 00:09:34,150 --> 00:09:36,010 background I'm going to try to remove 242 00:09:36,010 --> 00:09:40,120 the safe call operator there and also do 243 00:09:40,120 --> 00:09:44,130 the same for our download XML function 244 00:09:44,130 --> 00:09:46,600 download XML is our function so we're 245 00:09:46,600 --> 00:09:48,220 obviously free to modify that one all we 246 00:09:48,220 --> 00:09:50,320 want that doing background function you 247 00:09:50,320 --> 00:09:52,240 may remember what's generated for us in 248 00:09:52,240 --> 00:09:55,150 Android studio used a nullable type but 249 00:09:55,150 --> 00:09:57,010 our async task if you come up and have a 250 00:09:57,010 --> 00:09:58,750 look at that again that we've defined on 251 00:09:58,750 --> 00:10:02,650 line 15 doesn't use nullable types so if 252 00:10:02,650 --> 00:10:04,300 you're passing multiple values in an 253 00:10:04,300 --> 00:10:06,460 array then it may well be wise to leave 254 00:10:06,460 --> 00:10:09,160 the virag parameter as an array of a 255 00:10:09,160 --> 00:10:11,500 nullable objects and perform an old test 256 00:10:11,500 --> 00:10:13,390 inside doing background I'm not 257 00:10:13,390 --> 00:10:14,950 suggesting that you always remove that 258 00:10:14,950 --> 00:10:17,290 question mark but it is safe to do so 259 00:10:17,290 --> 00:10:19,720 here all right so that's our download 260 00:10:19,720 --> 00:10:21,820 data class finished in the next video 261 00:10:21,820 --> 00:10:23,590 we'll swing over and start working on 262 00:10:23,590 --> 00:10:25,660 our view model so I'll see you in the 263 00:10:25,660 --> 00:10:28,080 next video