1 00:00:00,000 --> 00:00:00,270 2 00:00:00,270 --> 00:00:02,370 TOMMY MACWILLIAM: In this video, we'll take a look 3 00:00:02,370 --> 00:00:06,510 at how to load some information from the internet into our app. 4 00:00:06,510 --> 00:00:09,420 Now in the last video when we wrote our Pokédex app, 5 00:00:09,420 --> 00:00:12,180 we just hardcoded that list of Pokémon. 6 00:00:12,180 --> 00:00:15,480 But we really want to do is load in all of that information 7 00:00:15,480 --> 00:00:20,250 from some resource on the internet so we don't have to hardcode it ourselves. 8 00:00:20,250 --> 00:00:22,680 The way we're going to do that is by utilizing something 9 00:00:22,680 --> 00:00:26,850 called an API, or Application Programming Interface. 10 00:00:26,850 --> 00:00:29,430 You can think about an API just as some code 11 00:00:29,430 --> 00:00:32,369 that somebody else wrote in a way that's designed 12 00:00:32,369 --> 00:00:35,620 for you to be able to easily use it. 13 00:00:35,620 --> 00:00:39,990 So the API that we're going to use is just going to return some data about 14 00:00:39,990 --> 00:00:45,600 Pokémon, and the format it's going to return that data in is called JSON. 15 00:00:45,600 --> 00:00:49,080 So JSON stands for JavaScript Object Notation, 16 00:00:49,080 --> 00:00:53,250 and it's this format that originally was used with just the programming language 17 00:00:53,250 --> 00:00:57,010 JavaScript, which is a language you can use to write web applications. 18 00:00:57,010 --> 00:01:00,940 But it's really evolved to become a standard format to transfer data, 19 00:01:00,940 --> 00:01:04,349 especially when it's hosted on some server 20 00:01:04,349 --> 00:01:07,480 and you're using some client to read that data. 21 00:01:07,480 --> 00:01:09,850 So here's what JSON looks like. 22 00:01:09,850 --> 00:01:13,050 You can see it's a little bit similar to some of the maps 23 00:01:13,050 --> 00:01:16,680 that we've seen in Java and that it looks like we have some keys, 24 00:01:16,680 --> 00:01:21,310 then there's a colon that separates these keys from some values. 25 00:01:21,310 --> 00:01:25,890 So to start we have these left and right curly braces, and these designate 26 00:01:25,890 --> 00:01:28,280 that this is an object. 27 00:01:28,280 --> 00:01:33,520 And inside of this object, we have three keys, and all these keys are strings. 28 00:01:33,520 --> 00:01:37,670 The first one is course, the second tracks, and the third is year. 29 00:01:37,670 --> 00:01:40,400 Then we have a colon, and on the right side of the colon 30 00:01:40,400 --> 00:01:44,100 we have the value that corresponds to that key. 31 00:01:44,100 --> 00:01:47,480 So the first value is a string, just CS50. 32 00:01:47,480 --> 00:01:53,430 The second value is a list, and this happens to be a list of strings. 33 00:01:53,430 --> 00:01:56,270 And then lastly this third value is a number. 34 00:01:56,270 --> 00:01:58,600 In this case, it's an integer. 35 00:01:58,600 --> 00:02:02,630 And so you can see that with JSON you can have a variety of different data 36 00:02:02,630 --> 00:02:05,120 types inside of the same object. 37 00:02:05,120 --> 00:02:10,370 And as you'd expect, you can also nest objects inside of each other. 38 00:02:10,370 --> 00:02:13,390 So the API that we're going to use is some website 39 00:02:13,390 --> 00:02:16,840 that someone else wrote called pokeapi.co. 40 00:02:16,840 --> 00:02:18,830 So let's check this out. 41 00:02:18,830 --> 00:02:21,577 So here's this API's homepage. 42 00:02:21,577 --> 00:02:24,160 This is pretty nice, because it gives you a lot of information 43 00:02:24,160 --> 00:02:27,390 about the type of data that's going to be returned by this API 44 00:02:27,390 --> 00:02:31,000 in this little sandbox where you can make requests yourself. 45 00:02:31,000 --> 00:02:32,350 So let's take a look. 46 00:02:32,350 --> 00:02:35,920 So it looks like the API request that we just made was 47 00:02:35,920 --> 00:02:41,290 to https://pokeai.co/api-- 48 00:02:41,290 --> 00:02:43,330 makes sense-- /v2-- 49 00:02:43,330 --> 00:02:45,850 so that probably stands for version two, so there's 50 00:02:45,850 --> 00:02:49,830 some version one around somewhere, but we don't have to worry about that-- 51 00:02:49,830 --> 00:02:52,210 /pokemon/ditto. 52 00:02:52,210 --> 00:02:54,670 So ditto is just a Pokémon. 53 00:02:54,670 --> 00:02:56,710 And then here you can see the information 54 00:02:56,710 --> 00:02:59,600 that this API is going to return. 55 00:02:59,600 --> 00:03:01,930 So there's lots of different information here. 56 00:03:01,930 --> 00:03:06,010 Some of these values are arrays, some of them are numbers, some of them 57 00:03:06,010 --> 00:03:07,510 are strings. 58 00:03:07,510 --> 00:03:11,110 If I come down here and click on this view raw JSON button, 59 00:03:11,110 --> 00:03:15,530 you can see the actual JSON that this API is going to return to us. 60 00:03:15,530 --> 00:03:19,570 So when we make a request to that URL, this is the information 61 00:03:19,570 --> 00:03:22,810 that we're going to get back. 62 00:03:22,810 --> 00:03:27,120 So the first thing we want to load from this API is a list of all 63 00:03:27,120 --> 00:03:28,675 of the Pokémon. 64 00:03:28,675 --> 00:03:30,550 So to figure out what I need to do, I'm going 65 00:03:30,550 --> 00:03:34,662 to jump to the documentation for this API. 66 00:03:34,662 --> 00:03:37,370 We're going to click on version two, since that's the latest one. 67 00:03:37,370 --> 00:03:39,010 Why not use that? 68 00:03:39,010 --> 00:03:41,360 And then you can see over here on the left 69 00:03:41,360 --> 00:03:44,990 there's lots of different information about all the different types 70 00:03:44,990 --> 00:03:47,150 of information you can get. 71 00:03:47,150 --> 00:03:52,150 So I'm looking for a list, so let me try clicking on resource lists. 72 00:03:52,150 --> 00:03:53,980 So it looks like here there's-- 73 00:03:53,980 --> 00:03:56,510 here's some policies about how to use it. 74 00:03:56,510 --> 00:03:58,470 There's a Slack if you want to ask questions. 75 00:03:58,470 --> 00:03:59,740 There's some libraries. 76 00:03:59,740 --> 00:04:02,490 We're not going to worry too much about those. 77 00:04:02,490 --> 00:04:05,440 Now let's take a look at this resource lists. 78 00:04:05,440 --> 00:04:08,680 So this says calling any API endpoint without a resource ID will 79 00:04:08,680 --> 00:04:10,970 return a paginated list of resources. 80 00:04:10,970 --> 00:04:11,470 Great. 81 00:04:11,470 --> 00:04:13,053 That's exactly what we're looking for. 82 00:04:13,053 --> 00:04:14,950 We're looking for a list of Pokémon. 83 00:04:14,950 --> 00:04:20,200 It also says that I can supply a limit parameter, so if I only want the first, 84 00:04:20,200 --> 00:04:24,160 say, 151 Pokémon, it's really easy for me to do that. 85 00:04:24,160 --> 00:04:26,650 So OK, this is basically all the information I need, 86 00:04:26,650 --> 00:04:30,560 so let's head back to that sandbox and give it a try. 87 00:04:30,560 --> 00:04:34,860 So it said to remove the ID, so I'm going to do that and just delete ditto. 88 00:04:34,860 --> 00:04:39,490 It also said that I can do something like give it a limit equals 151, 89 00:04:39,490 --> 00:04:42,940 so I'll give that a shot and hit Submit. 90 00:04:42,940 --> 00:04:46,160 And now we can see we got a different API response. 91 00:04:46,160 --> 00:04:51,760 It looks like I got this response where this is object with the key of results, 92 00:04:51,760 --> 00:04:56,560 and the value for that key is an array with 151 items. 93 00:04:56,560 --> 00:04:59,350 And if I check out what each item looks like, this looks great. 94 00:04:59,350 --> 00:05:01,300 Looks like we have the name of each pokemon, 95 00:05:01,300 --> 00:05:05,350 and then there's a URL there where I can get more information. 96 00:05:05,350 --> 00:05:07,100 So this is exactly what I was looking for. 97 00:05:07,100 --> 00:05:13,700 So this is the URL that I want to use to request that list of Pokémon. 98 00:05:13,700 --> 00:05:18,320 The library that I'm going to use to make a request to this API 99 00:05:18,320 --> 00:05:23,480 is this library that's provided to us by Google and Android called Volley. 100 00:05:23,480 --> 00:05:26,930 And if I open up the Developer.Android page here 101 00:05:26,930 --> 00:05:29,090 and look at the documentation for Volley, 102 00:05:29,090 --> 00:05:31,070 I can see there's lots of information here. 103 00:05:31,070 --> 00:05:32,827 And in fact there's a tutorial to walk you 104 00:05:32,827 --> 00:05:34,910 through how to make a bunch of different requests, 105 00:05:34,910 --> 00:05:37,020 but we're going to do that together. 106 00:05:37,020 --> 00:05:39,530 The important thing on this page is getting 107 00:05:39,530 --> 00:05:43,550 what this library is called so I can add it to my gradle file. 108 00:05:43,550 --> 00:05:45,710 By default this library isn't included. 109 00:05:45,710 --> 00:05:48,470 Just like we needed to include Recycler View separately, 110 00:05:48,470 --> 00:05:51,800 we'll also need to include this Volley library separately. 111 00:05:51,800 --> 00:05:56,940 So we can just take this and copy and paste it into our build.gradle file. 112 00:05:56,940 --> 00:05:57,890 So let's do that now. 113 00:05:57,890 --> 00:06:03,890 I'm just going to copy this, going to come back over here to Android Studio, 114 00:06:03,890 --> 00:06:09,930 and inside of my build.gradle file I'm just going to add this line. 115 00:06:09,930 --> 00:06:13,410 Again, we get this little information bar about syncing. 116 00:06:13,410 --> 00:06:17,040 So I'm going to do that, download the library from the internet, 117 00:06:17,040 --> 00:06:19,620 and put it somewhere that my project can use. 118 00:06:19,620 --> 00:06:20,140 There we go. 119 00:06:20,140 --> 00:06:22,350 Looks like our sync was successful, so now we 120 00:06:22,350 --> 00:06:26,730 have that library that we need to make those API requests. 121 00:06:26,730 --> 00:06:31,120 One last concept that we're going to see while we're making API requests 122 00:06:31,120 --> 00:06:34,210 is something called a try, catch block. 123 00:06:34,210 --> 00:06:38,030 So Java supports this language feature that's called exceptions. 124 00:06:38,030 --> 00:06:40,920 And an exception kind of, as it sounds, represents 125 00:06:40,920 --> 00:06:43,500 when something goes wrong with your application 126 00:06:43,500 --> 00:06:46,060 that you need to recover from. 127 00:06:46,060 --> 00:06:48,860 So here's what this syntax looks like. 128 00:06:48,860 --> 00:06:51,340 So let's say that we have some object here, 129 00:06:51,340 --> 00:06:54,220 and it has a method on it called something, 130 00:06:54,220 --> 00:06:58,540 and this something might fail in a way that we need to recover from. 131 00:06:58,540 --> 00:07:00,400 And so inside of the body of this it might 132 00:07:00,400 --> 00:07:03,100 say I'm going to throw some exception. 133 00:07:03,100 --> 00:07:05,800 And that means we should stop running our program 134 00:07:05,800 --> 00:07:08,710 and respond to that exception being thrown. 135 00:07:08,710 --> 00:07:11,890 In the case of our API, the exception we're worried about 136 00:07:11,890 --> 00:07:15,760 is if the API returns some JSON that's invalid. 137 00:07:15,760 --> 00:07:20,165 If it's invalid JSON and we can't decode it into some Java objects, 138 00:07:20,165 --> 00:07:22,540 then we need to really recover from that, because it just 139 00:07:22,540 --> 00:07:25,510 doesn't make sense to keep going trying to use some data 140 00:07:25,510 --> 00:07:27,530 if it's not formatted correctly. 141 00:07:27,530 --> 00:07:29,440 So this is the syntax we'll use. 142 00:07:29,440 --> 00:07:33,010 We start by saying try followed by an open brace. 143 00:07:33,010 --> 00:07:35,830 This just says that, inside of these open braces, 144 00:07:35,830 --> 00:07:38,950 something is going to throw some exception. 145 00:07:38,950 --> 00:07:42,550 Then we'll have a catch block, and this catch block 146 00:07:42,550 --> 00:07:47,350 is where your execution is going to jump to if an exception is thrown. 147 00:07:47,350 --> 00:07:51,490 So here we're catching just some exception called exception, that's 148 00:07:51,490 --> 00:07:53,347 a class name, so it's just a type. 149 00:07:53,347 --> 00:07:55,180 And then we'll name that exception called e, 150 00:07:55,180 --> 00:07:58,060 and now we have an exception object. 151 00:07:58,060 --> 00:08:01,090 And from that exception object we can do stuff. 152 00:08:01,090 --> 00:08:04,890 Simplest thing to do is just to print out what that exception is. 153 00:08:04,890 --> 00:08:07,480 So not only print out the message but also a stack 154 00:08:07,480 --> 00:08:10,753 trace showing you where the exception was triggered 155 00:08:10,753 --> 00:08:12,670 and all of the different functions and methods 156 00:08:12,670 --> 00:08:15,640 that you were inside when the exception happened. 157 00:08:15,640 --> 00:08:17,740 So when we're decoding JSON, we're going to need 158 00:08:17,740 --> 00:08:20,680 to use a try, catch block, and that's the reason we'll need it, 159 00:08:20,680 --> 00:08:24,920 is to sort of handle this kind of error in our decoding process. 160 00:08:24,920 --> 00:08:28,450 So those are all the concepts we need to start loading data from an API. 161 00:08:28,450 --> 00:08:31,040 So let's add that to our app. 162 00:08:31,040 --> 00:08:35,830 So let's open up Android Studio again and jump back to our adapter. 163 00:08:35,830 --> 00:08:39,778 Since our adapter was where all of our original data was stored, 164 00:08:39,778 --> 00:08:41,820 we're just going to make some modifications here. 165 00:08:41,820 --> 00:08:44,610 166 00:08:44,610 --> 00:08:50,310 So this was our previous data store, just the static list. 167 00:08:50,310 --> 00:08:55,700 So let's get rid of this and say that, instead of creating that list, 168 00:08:55,700 --> 00:09:01,560 let's just create a new empty array list. 169 00:09:01,560 --> 00:09:04,500 So now we're starting off with no data loaded 170 00:09:04,500 --> 00:09:07,680 and we're going to load that data in from an API. 171 00:09:07,680 --> 00:09:12,940 So first let's create a new method to load some data from that API. 172 00:09:12,940 --> 00:09:15,360 So we're going to say public, our return type 173 00:09:15,360 --> 00:09:17,577 is void because we're not returning anything-- 174 00:09:17,577 --> 00:09:19,410 we're just going to store it in that field-- 175 00:09:19,410 --> 00:09:21,935 and let's call this method loadPokemon. 176 00:09:21,935 --> 00:09:24,470 177 00:09:24,470 --> 00:09:28,610 So the first thing we'll need is the URL that we're looking to load. 178 00:09:28,610 --> 00:09:33,350 So let's create a new string variable called URL. 179 00:09:33,350 --> 00:09:39,180 And then if we jump back over to that API we can just copy and paste this. 180 00:09:39,180 --> 00:09:44,010 So we know it's going to be PokéAPI API version two, 181 00:09:44,010 --> 00:09:47,900 and then we can copy in the rest of the URL. 182 00:09:47,900 --> 00:09:53,800 So that's the URL that we want to load our data from. 183 00:09:53,800 --> 00:09:57,860 The next step is to write out a JSON request. 184 00:09:57,860 --> 00:10:00,850 So this is where we're going to use that Volley library. 185 00:10:00,850 --> 00:10:06,630 So inside of Volley there's this class called JSON object request, 186 00:10:06,630 --> 00:10:09,430 and as you'd guess this is a special request that's 187 00:10:09,430 --> 00:10:13,460 going to handle a JSON response. 188 00:10:13,460 --> 00:10:18,150 So let's create a new JSON object request. 189 00:10:18,150 --> 00:10:22,040 So the first parameter to this method is the type of request 190 00:10:22,040 --> 00:10:24,380 that we'd like to make. 191 00:10:24,380 --> 00:10:30,440 So to specify that, we're going to use the request class defined in Volley. 192 00:10:30,440 --> 00:10:34,610 Then we're going to say, method and get. 193 00:10:34,610 --> 00:10:37,820 So a get request is just a type of request, 194 00:10:37,820 --> 00:10:40,040 much like your web browser might make, that's 195 00:10:40,040 --> 00:10:41,840 just getting some data from a URL. 196 00:10:41,840 --> 00:10:43,190 We're not sending anything. 197 00:10:43,190 --> 00:10:45,260 We're just trying to get a list of Pokémon, 198 00:10:45,260 --> 00:10:48,140 so this get request makes sense. 199 00:10:48,140 --> 00:10:52,130 The next parameter to this method is the URL to request. 200 00:10:52,130 --> 00:10:52,790 That's easy. 201 00:10:52,790 --> 00:10:54,950 We just created URL. 202 00:10:54,950 --> 00:10:56,930 This next parameter we're not going to use. 203 00:10:56,930 --> 00:10:58,847 We're just going to pass null because we don't 204 00:10:58,847 --> 00:11:01,140 need to send along any information. 205 00:11:01,140 --> 00:11:04,940 And then lastly, we're going to define a method that's going 206 00:11:04,940 --> 00:11:08,150 to be called when the request finishes. 207 00:11:08,150 --> 00:11:11,000 So to do that, we're going to use a class also 208 00:11:11,000 --> 00:11:13,790 from Volley called response.listener. 209 00:11:13,790 --> 00:11:17,270 So we can say new response.listener, and again, 210 00:11:17,270 --> 00:11:20,830 let the autocomplete do the work for you here. 211 00:11:20,830 --> 00:11:24,820 So you'll notice what this did is it created an anonymous class 212 00:11:24,820 --> 00:11:27,250 in that same syntax we used before. 213 00:11:27,250 --> 00:11:31,960 So we're defining a new class that extends response.listener. 214 00:11:31,960 --> 00:11:34,680 It looks like it's passing in a type of JSON object, 215 00:11:34,680 --> 00:11:36,700 and that's being used here, because we know 216 00:11:36,700 --> 00:11:39,800 we're going to get back a JSON object. 217 00:11:39,800 --> 00:11:43,670 And then we're overriding this one method called onResponse. 218 00:11:43,670 --> 00:11:47,230 And this is the method that's going to be called for you automatically when 219 00:11:47,230 --> 00:11:49,120 the data finishes loading. 220 00:11:49,120 --> 00:11:51,700 So now that we've defined this method, let's 221 00:11:51,700 --> 00:11:55,090 start passing the response from the API. 222 00:11:55,090 --> 00:11:58,870 If we jump back to the API page, let's remember what 223 00:11:58,870 --> 00:12:01,310 their response is going to look like. 224 00:12:01,310 --> 00:12:04,390 It looks like we have an object with four keys here, 225 00:12:04,390 --> 00:12:08,420 but we really only care about this last one called results. 226 00:12:08,420 --> 00:12:12,380 And it also looks like the type of this results is an array, 227 00:12:12,380 --> 00:12:14,720 and it happens to have 151 items. 228 00:12:14,720 --> 00:12:17,730 229 00:12:17,730 --> 00:12:19,560 So we're going to start parsing this. 230 00:12:19,560 --> 00:12:27,300 So we're going to say we want adjacent array, and we'll call this results. 231 00:12:27,300 --> 00:12:30,780 And to access that key from that response object, 232 00:12:30,780 --> 00:12:37,250 we can say response get JSON array results. 233 00:12:37,250 --> 00:12:41,120 And so what this is going to do is it's going to look into that JSON, 234 00:12:41,120 --> 00:12:45,290 look for a key called results, and then take that key 235 00:12:45,290 --> 00:12:47,783 and make sure that it's an array. 236 00:12:47,783 --> 00:12:50,450 But you can see here that I already have this red underline that 237 00:12:50,450 --> 00:12:52,670 says unhandled exception. 238 00:12:52,670 --> 00:12:55,940 And this is where our try catch block is going to come into play. 239 00:12:55,940 --> 00:12:59,510 Cause in the event that there's no key called results or that key 240 00:12:59,510 --> 00:13:02,870 isn't actually an array, Java is going to throw an exception and say, 241 00:13:02,870 --> 00:13:05,900 this data doesn't look like what you thought it looked like 242 00:13:05,900 --> 00:13:08,060 and you need to handle that. 243 00:13:08,060 --> 00:13:09,210 So let's handle that. 244 00:13:09,210 --> 00:13:13,410 Let's put that inside of a try and now we can 245 00:13:13,410 --> 00:13:15,960 catch the exception that it's throwing. 246 00:13:15,960 --> 00:13:19,480 So if I just hover over this it says, unhandled exception, JSON exception. 247 00:13:19,480 --> 00:13:23,240 So let's just say JSON exception. 248 00:13:23,240 --> 00:13:24,990 And now at this point in a real app you'd 249 00:13:24,990 --> 00:13:28,230 want to somehow display a message to the user saying, you know, 250 00:13:28,230 --> 00:13:30,600 that some error occurred or try reloading. 251 00:13:30,600 --> 00:13:35,010 But for now let's just handle this ourselves and print it out to that log. 252 00:13:35,010 --> 00:13:41,790 So we can use that log class again, and this time say log.e, e for error. 253 00:13:41,790 --> 00:13:47,590 And we can say tag is just CS50, and we can say some JSON error. 254 00:13:47,590 --> 00:13:51,710 Then we can also pass along that exception object, 255 00:13:51,710 --> 00:13:54,920 and that way it can get logged. 256 00:13:54,920 --> 00:13:57,550 So let's quickly just do a make here. 257 00:13:57,550 --> 00:14:02,060 And it looks like I forgot a semicolon, so let's add that. 258 00:14:02,060 --> 00:14:06,740 And now there's one last parameter that we have to add to our JSON requests, 259 00:14:06,740 --> 00:14:09,510 and it's also going to be this anonymous class, 260 00:14:09,510 --> 00:14:12,530 but it's going to be an error listener. 261 00:14:12,530 --> 00:14:14,510 And so this is going to get called if something 262 00:14:14,510 --> 00:14:19,340 happens like this URL doesn't exist, and we won't worry about this too much. 263 00:14:19,340 --> 00:14:25,010 For now we can just sort of do another log.e, say CS50. 264 00:14:25,010 --> 00:14:30,050 We can say, Pokémon list error. 265 00:14:30,050 --> 00:14:32,160 Something simple like that. 266 00:14:32,160 --> 00:14:36,080 Now let's make sure our app compiles, and it does. 267 00:14:36,080 --> 00:14:38,960 So now let's get back to passing that JSON. 268 00:14:38,960 --> 00:14:43,520 So now we have this object called results of type JSON array. 269 00:14:43,520 --> 00:14:46,970 And so the next thing we want to do is iterate through this array 270 00:14:46,970 --> 00:14:50,040 and add each of those results to our list. 271 00:14:50,040 --> 00:14:52,070 So to do that, we're going to write a for loop 272 00:14:52,070 --> 00:14:53,898 to iterate through all of those elements, 273 00:14:53,898 --> 00:14:55,940 and we'll just write a traditional for loop here. 274 00:14:55,940 --> 00:15:00,260 So we'll say int i equals zero, i is less than results, 275 00:15:00,260 --> 00:15:04,600 and this object has this method called length that's defined on it. 276 00:15:04,600 --> 00:15:05,780 And we'll say i plus plus. 277 00:15:05,780 --> 00:15:09,300 278 00:15:09,300 --> 00:15:12,870 And so now to access each individual element 279 00:15:12,870 --> 00:15:17,160 we can say there's some object that's a JSON object that 280 00:15:17,160 --> 00:15:25,610 represents a single result, and that's going to be results.GetJSONObject of i. 281 00:15:25,610 --> 00:15:29,390 And so now each of these objects represents 282 00:15:29,390 --> 00:15:31,560 a single one of these elements. 283 00:15:31,560 --> 00:15:35,710 So this object should have two keys, one called name and one called URL. 284 00:15:35,710 --> 00:15:38,560 285 00:15:38,560 --> 00:15:42,820 So if now we want to create these Pokémon objects, 286 00:15:42,820 --> 00:15:46,740 we want to make sure there's a place for both the name and the URL. 287 00:15:46,740 --> 00:15:49,880 And if you remember what our model looks like, it looks a little different. 288 00:15:49,880 --> 00:15:51,650 We have name and number. 289 00:15:51,650 --> 00:15:54,370 So let's just quickly update this to have a URL. 290 00:15:54,370 --> 00:16:04,250 291 00:16:04,250 --> 00:16:08,140 So we'll change the field name, we'll change the parameter, 292 00:16:08,140 --> 00:16:14,080 and lastly we'll change our getter to be getURL and return URL. 293 00:16:14,080 --> 00:16:16,690 So now we have a place to store both of those things. 294 00:16:16,690 --> 00:16:20,040 295 00:16:20,040 --> 00:16:21,650 So now to actually store them. 296 00:16:21,650 --> 00:16:29,100 We're going to say Pokémon.add, and now we can create a new Pokémon object. 297 00:16:29,100 --> 00:16:30,960 Remember, that constructor takes two things. 298 00:16:30,960 --> 00:16:36,540 It takes a name, and so that's going to be result.getString, 299 00:16:36,540 --> 00:16:37,760 and that was called name. 300 00:16:37,760 --> 00:16:40,290 301 00:16:40,290 --> 00:16:43,280 Just space this out. 302 00:16:43,280 --> 00:16:50,740 And the other argument is result.getString, 303 00:16:50,740 --> 00:16:53,850 and we called this URL. 304 00:16:53,850 --> 00:16:56,640 305 00:16:56,640 --> 00:16:59,000 Now we'll add a semicolon. 306 00:16:59,000 --> 00:17:02,540 And let's make sure our app compiles. 307 00:17:02,540 --> 00:17:04,410 Looks like we're missing a-- 308 00:17:04,410 --> 00:17:06,770 oh, had an extra semicolon there. 309 00:17:06,770 --> 00:17:10,680 310 00:17:10,680 --> 00:17:14,290 And now remember we sort of changed that Pokémon object, 311 00:17:14,290 --> 00:17:18,220 so we got rid of this getNumber method, so let's just comment this out for now, 312 00:17:18,220 --> 00:17:20,560 and we'll come back to this later. 313 00:17:20,560 --> 00:17:21,435 So there's one there. 314 00:17:21,435 --> 00:17:24,119 315 00:17:24,119 --> 00:17:26,839 And it looks like that's the only usage of it. 316 00:17:26,839 --> 00:17:31,720 OK, so now we should have a list of Pokémon objects, 317 00:17:31,720 --> 00:17:39,960 but this time loaded from an API rather than that static list. 318 00:17:39,960 --> 00:17:43,130 So the last thing we need to do here is to actually kick off 319 00:17:43,130 --> 00:17:46,490 this request so it actually starts running. 320 00:17:46,490 --> 00:17:51,750 So to do that, we're going to use an object called a request queue. 321 00:17:51,750 --> 00:17:53,660 So this is from the Volley documentation. 322 00:17:53,660 --> 00:17:57,240 You can read about that. 323 00:17:57,240 --> 00:18:03,040 But we're going to create an object of type request queue, 324 00:18:03,040 --> 00:18:06,490 and we'll just call it request queue. 325 00:18:06,490 --> 00:18:09,540 And if you look in the documentation, this object 326 00:18:09,540 --> 00:18:13,680 requires a parameter that's called a context. 327 00:18:13,680 --> 00:18:17,880 And right now our Pokédex adapter doesn't have access to that context, 328 00:18:17,880 --> 00:18:20,280 but our Pokémon activity does. 329 00:18:20,280 --> 00:18:24,300 There's a method on activities that's called getApplicationContext. 330 00:18:24,300 --> 00:18:31,040 And so we want to do is pass that object from our activity to the adapter. 331 00:18:31,040 --> 00:18:32,290 And that's pretty easy to do. 332 00:18:32,290 --> 00:18:35,430 Let's just create a constructor. 333 00:18:35,430 --> 00:18:39,050 So we'll say our Pokédex adapter constructor takes one thing, 334 00:18:39,050 --> 00:18:44,900 it takes a context, and we'll just call it context. 335 00:18:44,900 --> 00:18:49,280 And now with that context we can create our request queue. 336 00:18:49,280 --> 00:18:55,620 So we can say request queue equals Volley.newRequestQueue, 337 00:18:55,620 --> 00:19:01,200 and this is where we're going to pass in that context variable. 338 00:19:01,200 --> 00:19:04,690 Inside of this constructor is where we can add our API requests. 339 00:19:04,690 --> 00:19:09,900 So let's just say loadPokémon right there. 340 00:19:09,900 --> 00:19:12,710 Lastly, with this request queue, we want to make sure 341 00:19:12,710 --> 00:19:14,940 that our request is actually added to it. 342 00:19:14,940 --> 00:19:20,890 So when I say requestQueue.add request, this 343 00:19:20,890 --> 00:19:25,030 is what's actually going to kick off the request and actually make the request. 344 00:19:25,030 --> 00:19:27,100 In this first line here, all I've done is 345 00:19:27,100 --> 00:19:29,950 define an object that represents a request, 346 00:19:29,950 --> 00:19:32,140 but I haven't actually used it yet. 347 00:19:32,140 --> 00:19:36,340 So to actually use it, all I have to say is I'm going to add it to this queue, 348 00:19:36,340 --> 00:19:41,470 and this queue is going to actually make that request to pokeapi.co. 349 00:19:41,470 --> 00:19:44,330 So we changed the constructor for our Pokédex adapter, 350 00:19:44,330 --> 00:19:47,120 so now we also need to change our main activity. 351 00:19:47,120 --> 00:19:49,450 So here is where we created the Pokédex adapter, 352 00:19:49,450 --> 00:19:52,330 and so you notice now that we have a syntax error, which makes sense, 353 00:19:52,330 --> 00:19:55,840 because we asked the constructor to take one parameter. 354 00:19:55,840 --> 00:19:58,540 So we're just going to call that getApplicationContext. 355 00:19:58,540 --> 00:20:01,270 This is just a method that's defined on activity. 356 00:20:01,270 --> 00:20:05,080 So we're just going to call this and now we can pass along that field 357 00:20:05,080 --> 00:20:07,720 that our request library needs. 358 00:20:07,720 --> 00:20:08,890 So let's give this a shot. 359 00:20:08,890 --> 00:20:12,460 Let's make sure that this compiles. 360 00:20:12,460 --> 00:20:13,310 Looks like it does. 361 00:20:13,310 --> 00:20:16,660 So let's now try running this inside of the simulator. 362 00:20:16,660 --> 00:20:19,798 Looks like we installed successfully, so let's open it up. 363 00:20:19,798 --> 00:20:21,430 Hmm. 364 00:20:21,430 --> 00:20:24,260 Looks like nothing's there. 365 00:20:24,260 --> 00:20:28,590 So our API requests went through and we loaded all of this data, 366 00:20:28,590 --> 00:20:34,400 but now we need to notify our Recycler View that our data actually changed. 367 00:20:34,400 --> 00:20:37,520 All we've done is just change this underlying model, 368 00:20:37,520 --> 00:20:41,460 but we need to tell the Recycler View, hey, go ahead and reload that data 369 00:20:41,460 --> 00:20:43,982 so you can display the latest stuff. 370 00:20:43,982 --> 00:20:45,190 And that's pretty easy to do. 371 00:20:45,190 --> 00:20:50,470 The only thing we need to do is call this method notifyDataSetChanged. 372 00:20:50,470 --> 00:20:55,150 And this is a method that's defined on the RecyclerView.Adapter class. 373 00:20:55,150 --> 00:20:56,740 We didn't have to write this. 374 00:20:56,740 --> 00:21:00,590 Because we're extending that, we can just call that method. 375 00:21:00,590 --> 00:21:04,010 So now that I've added that notifyDataSetChanged method, 376 00:21:04,010 --> 00:21:05,410 let's try again. 377 00:21:05,410 --> 00:21:08,080 Looks like we installed successfully. 378 00:21:08,080 --> 00:21:09,160 We open the app-- 379 00:21:09,160 --> 00:21:10,330 still blank. 380 00:21:10,330 --> 00:21:14,290 So let's take a look at what's output in our log. 381 00:21:14,290 --> 00:21:17,770 So let's come down here to the logcat, open that up, 382 00:21:17,770 --> 00:21:22,270 and if we scroll up a bit, looks like this red doesn't look good. 383 00:21:22,270 --> 00:21:26,140 So here's that Pokemon list error, which means that this on error response 384 00:21:26,140 --> 00:21:27,550 is being triggered. 385 00:21:27,550 --> 00:21:29,290 It says that I got permission denied. 386 00:21:29,290 --> 00:21:31,910 I'm missing the Internet permission. 387 00:21:31,910 --> 00:21:35,770 So if you remember back to when we're looking at that Android manifest XML 388 00:21:35,770 --> 00:21:39,280 file, we saw there that that's where we listed a few things about what 389 00:21:39,280 --> 00:21:41,490 our application is allowed to do. 390 00:21:41,490 --> 00:21:44,290 Because by default Android apps are basically in a sandbox 391 00:21:44,290 --> 00:21:46,630 where they only have certain permissions. 392 00:21:46,630 --> 00:21:48,670 And one of the permissions that we need to add 393 00:21:48,670 --> 00:21:51,820 is the ability to communicate to the internet. 394 00:21:51,820 --> 00:21:53,900 That's not something that's added by default. 395 00:21:53,900 --> 00:21:58,060 So we have to go into our Android manifest and add that ourselves. 396 00:21:58,060 --> 00:22:00,970 To do that, we're going to open back up that Android 397 00:22:00,970 --> 00:22:09,610 manifest and, underneath this application tag, we're going to add 398 00:22:09,610 --> 00:22:10,990 uses permission. 399 00:22:10,990 --> 00:22:12,940 Again, autocomplete is right there for me. 400 00:22:12,940 --> 00:22:16,030 It says internet is probably something you want to add. 401 00:22:16,030 --> 00:22:19,760 So we're just going to let that autocomplete and we're good to go. 402 00:22:19,760 --> 00:22:21,730 So this is a new XML element. 403 00:22:21,730 --> 00:22:24,430 Says I want to use a permission, that permission 404 00:22:24,430 --> 00:22:28,300 is this special Android permission that lets you communicate with the internet. 405 00:22:28,300 --> 00:22:31,310 So now our app is allowed to do that. 406 00:22:31,310 --> 00:22:32,860 So let's run it one last time. 407 00:22:32,860 --> 00:22:35,810 408 00:22:35,810 --> 00:22:36,380 Great. 409 00:22:36,380 --> 00:22:39,680 This time we have no errors in our logs, and in fact we've 410 00:22:39,680 --> 00:22:43,370 loaded up all of this data from the API. 411 00:22:43,370 --> 00:22:47,830 So we can see that we're using this API response now in our app, 412 00:22:47,830 --> 00:22:51,140 and our Recycler View is basically displaying data that we 413 00:22:51,140 --> 00:22:54,010 got from somewhere on the internet. 414 00:22:54,010 --> 00:22:57,970 If you remember before, when we hardcoded those values, 415 00:22:57,970 --> 00:23:00,640 we just sort of uppercased the first letter ourselves, 416 00:23:00,640 --> 00:23:02,440 because we were typing it in ourselves. 417 00:23:02,440 --> 00:23:04,510 And it looks like this API doesn't do that, 418 00:23:04,510 --> 00:23:06,950 but it looks a lot nicer when it's capitalized. 419 00:23:06,950 --> 00:23:10,180 So let's write that capitalization ourself. 420 00:23:10,180 --> 00:23:13,290 Let's jump back to the Pokédex adapter. 421 00:23:13,290 --> 00:23:19,580 And now rather than just using whatever field is returned under that name key, 422 00:23:19,580 --> 00:23:23,520 let's do something with that before we create the Pokémon object. 423 00:23:23,520 --> 00:23:25,640 So let's create a variable name, and that's 424 00:23:25,640 --> 00:23:28,241 going to be equal to result.getStringName. 425 00:23:28,241 --> 00:23:31,120 426 00:23:31,120 --> 00:23:33,920 And so now let's capitalize the first letter. 427 00:23:33,920 --> 00:23:38,390 To do that, I want to take the first item in this string, the first letter 428 00:23:38,390 --> 00:23:41,450 in this string, capitalize that, and then 429 00:23:41,450 --> 00:23:45,110 append onto it the rest of the string. 430 00:23:45,110 --> 00:23:47,750 So luckily, Java strings have a method called 431 00:23:47,750 --> 00:23:53,013 substring that you can use to get sort of a string inside of that string. 432 00:23:53,013 --> 00:23:53,930 So here's what I mean. 433 00:23:53,930 --> 00:24:00,230 If I say name.Substring, you can see here 434 00:24:00,230 --> 00:24:04,410 the autocomplete tells me that it takes two arguments, a begin and an end. 435 00:24:04,410 --> 00:24:12,500 So to get just the first letter, I want to take a begin index of zero 436 00:24:12,500 --> 00:24:15,270 and an end index of one. 437 00:24:15,270 --> 00:24:17,330 That's going to get me the first letter. 438 00:24:17,330 --> 00:24:20,070 And with that first letter, I want to uppercase it. 439 00:24:20,070 --> 00:24:23,210 So I can say, toUppercase. 440 00:24:23,210 --> 00:24:25,550 And then I just want the rest of the string 441 00:24:25,550 --> 00:24:28,050 as it was, because that's already lowercase, 442 00:24:28,050 --> 00:24:31,190 so let's just say name dot substring. 443 00:24:31,190 --> 00:24:34,670 Now if I just give this one argument, what it's going to do 444 00:24:34,670 --> 00:24:36,690 is take the rest of the substring. 445 00:24:36,690 --> 00:24:38,900 So I don't need to specify an end index, it'll 446 00:24:38,900 --> 00:24:42,120 just keep going until it hits the end of the string. 447 00:24:42,120 --> 00:24:43,910 So now let's run this. 448 00:24:43,910 --> 00:24:45,890 We open up the emulator. 449 00:24:45,890 --> 00:24:47,540 That's what we wanted. 450 00:24:47,540 --> 00:24:51,800 Now we have everything capitalized and looking like it did before. 451 00:24:51,800 --> 00:24:55,490 So now that we've loaded the list of Pokémon from this API, 452 00:24:55,490 --> 00:24:59,460 let's also load in the data about a single pokemon. 453 00:24:59,460 --> 00:25:01,980 To do that, let's first jump back to the API 454 00:25:01,980 --> 00:25:04,980 to remind ourselves what that data looks like. 455 00:25:04,980 --> 00:25:11,100 So we can use this URL parameter to say what request we need to make to get 456 00:25:11,100 --> 00:25:13,440 information about each Pokémon. 457 00:25:13,440 --> 00:25:18,450 So if we take the first one, I can get rid of this limit to say /1, 458 00:25:18,450 --> 00:25:22,980 since that's what this URL is telling me to get, and click Submit. 459 00:25:22,980 --> 00:25:25,860 And so this is the resource that we're going to get back. 460 00:25:25,860 --> 00:25:30,710 It has a bunch of different information about the Pokémon. 461 00:25:30,710 --> 00:25:35,900 And so let's say that in our app we want to display the type of each pokemon. 462 00:25:35,900 --> 00:25:40,280 So each Pokémon can have one or two types associated with it, 463 00:25:40,280 --> 00:25:45,620 and then it's given to us in the API with this types field. 464 00:25:45,620 --> 00:25:51,500 So what we want to do is, in our second activity, once that's loaded, 465 00:25:51,500 --> 00:25:56,150 we want to load up this information and then use the types field 466 00:25:56,150 --> 00:26:00,290 and display that via some other text views in the app. 467 00:26:00,290 --> 00:26:04,490 So just as we did last time, let's first change the view 468 00:26:04,490 --> 00:26:08,960 and add the elements we want to add, see if we get any changes to our model, 469 00:26:08,960 --> 00:26:11,690 and then finally hook up the controller. 470 00:26:11,690 --> 00:26:15,920 So let's open up that activity Pokemon XML file, where we have those text 471 00:26:15,920 --> 00:26:19,110 views, and let's add a few more. 472 00:26:19,110 --> 00:26:21,030 Let's just copy here. 473 00:26:21,030 --> 00:26:27,100 So we want one to be called our Pokémon type one, 474 00:26:27,100 --> 00:26:34,580 and the other we'll call Pokémon type two. 475 00:26:34,580 --> 00:26:36,950 Feel free to adjust the text size or padding. 476 00:26:36,950 --> 00:26:40,430 I'm just going to leave them alone for now. 477 00:26:40,430 --> 00:26:45,450 So next, let's open up our Pokémon activity. 478 00:26:45,450 --> 00:26:49,272 So remember last time that we passed along the name and the number. 479 00:26:49,272 --> 00:26:50,730 This time we don't need to do that. 480 00:26:50,730 --> 00:26:54,570 What we actually want to pass along is that URL, 481 00:26:54,570 --> 00:26:59,250 since we can use that URL to load in information about a Pokémon. 482 00:26:59,250 --> 00:27:04,830 So rather than getting name here, let's get URL and call this parameter URL. 483 00:27:04,830 --> 00:27:08,240 484 00:27:08,240 --> 00:27:11,990 Now we can delete everything that's referencing number here 485 00:27:11,990 --> 00:27:15,920 and we can delete this as well. 486 00:27:15,920 --> 00:27:20,380 And finally, let's move this URL just to a field so we can use it later. 487 00:27:20,380 --> 00:27:24,080 488 00:27:24,080 --> 00:27:24,950 And there we go. 489 00:27:24,950 --> 00:27:27,640 So all we're doing is saving some URL that's 490 00:27:27,640 --> 00:27:30,580 passed into us from the internet. 491 00:27:30,580 --> 00:27:35,800 OK, so just as we did last time, let's make a new method to load in some data 492 00:27:35,800 --> 00:27:37,250 from the API. 493 00:27:37,250 --> 00:27:42,290 So let's call this public void, let's just call it load. 494 00:27:42,290 --> 00:27:45,090 And then rather than writing all of that stuff by hand again, 495 00:27:45,090 --> 00:27:51,220 let's just come back to our adapter and just copy what we had before. 496 00:27:51,220 --> 00:27:54,658 And when we paste this code you'll notice that Android Studio is telling 497 00:27:54,658 --> 00:27:57,200 us it looks like there's a bunch of objects you're using here 498 00:27:57,200 --> 00:27:58,708 that you haven't imported yet. 499 00:27:58,708 --> 00:28:01,250 And if I just click OK, it's going to import them all from me 500 00:28:01,250 --> 00:28:04,580 automatically, which is pretty nice. 501 00:28:04,580 --> 00:28:07,850 So the first thing we want to change is this URL. 502 00:28:07,850 --> 00:28:09,690 We don't need to use this anymore. 503 00:28:09,690 --> 00:28:16,180 In fact, we've already saved the URL we want to call, so let's get rid of that. 504 00:28:16,180 --> 00:28:19,660 Next, our results field is going to be a bit different. 505 00:28:19,660 --> 00:28:20,965 So let's just get rid of this. 506 00:28:20,965 --> 00:28:25,010 507 00:28:25,010 --> 00:28:28,440 Finally, let's change our error messages so they're a bit easier to read. 508 00:28:28,440 --> 00:28:31,980 So this is, let's say, a Pokémon JSON error, 509 00:28:31,980 --> 00:28:35,120 and this let's call it a Pokémon details error. 510 00:28:35,120 --> 00:28:38,810 So that way we just know what's being triggered here. 511 00:28:38,810 --> 00:28:42,760 And now let's parse this new JSON response. 512 00:28:42,760 --> 00:28:49,470 So if we come back to that API, let's remember what we're looking for. 513 00:28:49,470 --> 00:28:53,500 The first thing we're looking for are types. 514 00:28:53,500 --> 00:28:59,110 So it looks like this types field has a list of objects, 515 00:28:59,110 --> 00:29:07,900 so we can say response.getJSONArray, and that's types. 516 00:29:07,900 --> 00:29:15,650 And so let's just assign that to a JSON array called type entries. 517 00:29:15,650 --> 00:29:18,260 So just like we did before, let's iterate through this. 518 00:29:18,260 --> 00:29:26,450 Let's say for i is zero, is is less than type entries.length, i plus plus. 519 00:29:26,450 --> 00:29:30,680 So let's remind ourselves what each entry in this list looks like. 520 00:29:30,680 --> 00:29:35,510 It looks like it's an array of JSON objects, and each of those objects 521 00:29:35,510 --> 00:29:39,530 has two keys, one called slot and one called type. 522 00:29:39,530 --> 00:29:41,870 So let's get our slot first. 523 00:29:41,870 --> 00:29:48,990 So we want to say JSONObject, we'll call this a type entry, 524 00:29:48,990 --> 00:29:56,020 is type entries.JSONObject, and we'll pass along the index to get. 525 00:29:56,020 --> 00:30:05,650 Now we can have a slot integer that's just type entry.getInt slot. 526 00:30:05,650 --> 00:30:08,930 So that's reading the first value from that API. 527 00:30:08,930 --> 00:30:11,350 So now let's read the second. 528 00:30:11,350 --> 00:30:13,660 To do that, let's create a string. 529 00:30:13,660 --> 00:30:15,940 We'll call it type. 530 00:30:15,940 --> 00:30:18,370 And now we'll say type entry.getJSONObject. 531 00:30:18,370 --> 00:30:21,330 532 00:30:21,330 --> 00:30:23,140 We remember that was called type. 533 00:30:23,140 --> 00:30:30,900 And we only want the name field here, so we can just say getString name. 534 00:30:30,900 --> 00:30:32,730 Let's double check that that's right. 535 00:30:32,730 --> 00:30:36,120 We have a type and a name, so that looks good. 536 00:30:36,120 --> 00:30:38,640 So now that we have these two variables in memory, 537 00:30:38,640 --> 00:30:41,962 let's use them to display something in the UI. 538 00:30:41,962 --> 00:30:43,920 So the first thing I want to do is, just like I 539 00:30:43,920 --> 00:30:48,090 did before I had these text view fields, let's add those other two text view 540 00:30:48,090 --> 00:30:50,050 fields that we just created. 541 00:30:50,050 --> 00:30:58,370 So one was called type one text view, and the other was called type two text 542 00:30:58,370 --> 00:30:59,630 view. 543 00:30:59,630 --> 00:31:02,720 Just as we did up here, let's use findViewByID. 544 00:31:02,720 --> 00:31:10,750 So we'll say type one text view is findViewByID type one, 545 00:31:10,750 --> 00:31:18,820 and our type two text view is findViewByID type two. 546 00:31:18,820 --> 00:31:22,300 Now we can use these two fields just as we did before. 547 00:31:22,300 --> 00:31:29,680 We can say, if we're in the first slot, then use type one text view, set text, 548 00:31:29,680 --> 00:31:32,770 and we'll just use that type variable. 549 00:31:32,770 --> 00:31:37,190 And if we're in slot two, we'll use the other text view. 550 00:31:37,190 --> 00:31:43,910 551 00:31:43,910 --> 00:31:44,880 OK. 552 00:31:44,880 --> 00:31:47,300 And something else I like to do is just, to make sure 553 00:31:47,300 --> 00:31:50,690 that those fields are empty, we can up here just say, 554 00:31:50,690 --> 00:31:55,490 type one text view, let's just set that to the empty string 555 00:31:55,490 --> 00:31:57,590 and set this to the empty string. 556 00:31:57,590 --> 00:32:00,337 Sometimes when I'm making views I like to use placeholder values 557 00:32:00,337 --> 00:32:03,420 just so I can get a sense for what the view will look like with real data. 558 00:32:03,420 --> 00:32:05,253 So this just makes sure that those are gone. 559 00:32:05,253 --> 00:32:07,670 560 00:32:07,670 --> 00:32:10,370 And let's make sure this is type two. 561 00:32:10,370 --> 00:32:11,730 OK, so that's the types. 562 00:32:11,730 --> 00:32:17,330 So let's add back in the name and the number since we got rid of those. 563 00:32:17,330 --> 00:32:21,040 Let's come back up here and do that. 564 00:32:21,040 --> 00:32:24,210 So let's jump back to our response just to remind ourselves 565 00:32:24,210 --> 00:32:25,797 what this looks like. 566 00:32:25,797 --> 00:32:27,880 So it looks like there's two keys we can use here. 567 00:32:27,880 --> 00:32:28,890 One is called name. 568 00:32:28,890 --> 00:32:30,390 That's just the name of the Pokémon. 569 00:32:30,390 --> 00:32:33,230 And the other is ID, and that's the number. 570 00:32:33,230 --> 00:32:37,720 So we're going to have the same code we had before, just using this API data. 571 00:32:37,720 --> 00:32:42,895 So we'll say my name text view, let's set the text to be response.getString. 572 00:32:42,895 --> 00:32:46,200 573 00:32:46,200 --> 00:32:47,850 It's called name. 574 00:32:47,850 --> 00:32:50,940 And our number text view, same thing before. 575 00:32:50,940 --> 00:32:54,780 We're going to set text, we're going to use string.format. 576 00:32:54,780 --> 00:33:01,400 Our format string is going to be 03d, meeting we want a three digit number. 577 00:33:01,400 --> 00:33:11,210 We're going to pass in response.getInt, and that was called ID. 578 00:33:11,210 --> 00:33:17,370 Now if we save it, let's compile, see if we have any errors. 579 00:33:17,370 --> 00:33:18,450 Doesn't look like we do. 580 00:33:18,450 --> 00:33:20,010 That's great. 581 00:33:20,010 --> 00:33:25,630 So the last thing we need to do is to pass in this URL to this activity. 582 00:33:25,630 --> 00:33:27,360 This was just this kind of second half. 583 00:33:27,360 --> 00:33:29,520 Let's go back to that first half. 584 00:33:29,520 --> 00:33:35,370 So let's come back to our Pokédex adapter and look at that click handler. 585 00:33:35,370 --> 00:33:39,590 So OK, looks like before our click handler was passing in an extra, one 586 00:33:39,590 --> 00:33:41,480 called name, one called number. 587 00:33:41,480 --> 00:33:46,110 Let's now pass in an extra called URL. 588 00:33:46,110 --> 00:33:49,880 And remember that our Pokémon object has this method getURL, 589 00:33:49,880 --> 00:33:53,210 and that's going to get that URL as a string. 590 00:33:53,210 --> 00:33:55,550 Now we only need to pass that in, because we're 591 00:33:55,550 --> 00:33:58,070 no longer using the name and the number from that object. 592 00:33:58,070 --> 00:34:00,350 We just care about that URL. 593 00:34:00,350 --> 00:34:03,580 So let's run this and see what happens. 594 00:34:03,580 --> 00:34:06,160 Looks like everything installed successfully. 595 00:34:06,160 --> 00:34:08,870 Here's our list just like we expected from last time, 596 00:34:08,870 --> 00:34:13,030 and let's try tapping on a Pokémon. 597 00:34:13,030 --> 00:34:14,350 Looks like nothing happened. 598 00:34:14,350 --> 00:34:15,865 Let's think about why. 599 00:34:15,865 --> 00:34:22,300 If we jump back to our Pokémon activity, it looks like we created this request, 600 00:34:22,300 --> 00:34:27,040 but Android Studio has this sort of underlined and gray and it says 601 00:34:27,040 --> 00:34:28,480 it's never used. 602 00:34:28,480 --> 00:34:31,570 And remember, last time before we could actually make the request 603 00:34:31,570 --> 00:34:34,330 we needed to add it to that request queue. 604 00:34:34,330 --> 00:34:37,989 So let's create another request queue just like we did last time. 605 00:34:37,989 --> 00:34:39,340 Say requestQueue. 606 00:34:39,340 --> 00:34:44,280 607 00:34:44,280 --> 00:34:47,280 And then we can create one using that same line as last time. 608 00:34:47,280 --> 00:34:54,830 We can say, my requestQueue is equal to Volley.newRequestQueue. 609 00:34:54,830 --> 00:34:57,710 Again, we just need to pass in that application context. 610 00:34:57,710 --> 00:35:01,300 Because we're in an activity, we already have access to it. 611 00:35:01,300 --> 00:35:03,950 So that's going to create the request queue. 612 00:35:03,950 --> 00:35:05,870 And now let's use it. 613 00:35:05,870 --> 00:35:08,090 Let's say requestQueue.addRequest. 614 00:35:08,090 --> 00:35:12,520 615 00:35:12,520 --> 00:35:15,520 And notice that same gray underline is also on this load method, 616 00:35:15,520 --> 00:35:17,210 because that's never used. 617 00:35:17,210 --> 00:35:19,360 So let's just call that method immediately 618 00:35:19,360 --> 00:35:20,930 when the activity is created. 619 00:35:20,930 --> 00:35:24,640 So after we've wired up all of our views, we've created the queue, 620 00:35:24,640 --> 00:35:29,170 now let's call this load method so we actually make that API request. 621 00:35:29,170 --> 00:35:31,170 Now let's try running it again. 622 00:35:31,170 --> 00:35:32,410 OK, looks like we're running. 623 00:35:32,410 --> 00:35:33,290 Let's try again. 624 00:35:33,290 --> 00:35:36,700 625 00:35:36,700 --> 00:35:37,690 There we go. 626 00:35:37,690 --> 00:35:40,450 So we can see here that the activity was blank for a second 627 00:35:40,450 --> 00:35:42,280 just as it was loading in the data. 628 00:35:42,280 --> 00:35:45,060 But now here's that data that came in from the API. 629 00:35:45,060 --> 00:35:48,180 We have the name, the number, and both of the types. 630 00:35:48,180 --> 00:35:49,920 And you can try any of the Pokémon. 631 00:35:49,920 --> 00:35:53,070 You can type in anything and we're going to get exactly the response 632 00:35:53,070 --> 00:35:54,820 from that API. 633 00:35:54,820 --> 00:36:00,060 So that's how you can use Java to load information from an API 634 00:36:00,060 --> 00:36:03,140 and bring it into your app. 635 00:36:03,140 --> 00:36:04,818