Networking and FutureBuilder (The Boring Flutter Development Show, Ep. 3)

[MUSIC PLAYING] ANDREW: Hey, everybody Welcome back to The Boring Show MATT: Hi, everyone I am not Filip ANDREW: So I’m Andrew Again, this is Matt this time So we’re changing up the cast a little bit here If you haven’t seen The Boring Show before, this is about an hour long show, where two Flutter engineers just work on an app, covering some interesting things, make mistakes, look things up, and occasionally interact with comments that you guys leave on our previous episodes and via Twitter So we’re going to have some of that as well MATT: So that’s great So I get to make mistakes ANDREW: Yes MATT: OK, perfect Well, we’ll see plenty of that Good ANDREW: Yeah, excellent So when last we left our app, which is a Hacker News reader, we had just gotten built_value into the application And we had basically gotten an article object that was being generated correctly with source gen and built_value But it only had one property, which was ID And if we look at the Hacker News API, which is what we want to deserialize with this object, there’s a lot more than ID in there So we have all these fields that we’re going to need to be able to automatically pull in from JSON and populate one of these article objects with So the first thing I’m going to do here is try and finish up the built_value portion that we started last time by adding the rest of these fields MATT: Cool, so we’re going to build value for this ANDREW: Yes MATT: OK, that’s– ANDREW: Unless we run into a snag, in which case we can backtrack and use JSON serializable or something else MATT: We’ll do it by hand ANDREW: Yeah MATT: OK ANDREW: It’s only one little object, so who knows So I’m going to go and grab all of these properties through the magic of cutting and pasting And this is our old article This is going to break many things, because we already had that out We had made a second file for it, so I need to get all those extra properties into this article class, so that when built value runs, it’ll do all of the serialization stuff for it So let me go ahead and paste here And this is going to take me just a second Have you used built_value yet in anything? MATT: I’ve used built_value a couple of times built_value is great for when your incoming JSON roughly matches the structure of your class pretty well ANDREW: Yeah, that’s true If you need to sort of massage stuff, sure MATT: You talk about built_values, immutability stuff last week ANDREW: We touched on it I think that’ll– we haven’t done an app state management episode yet, which is something we do need to get to We saw that in the comments People are curious about it And so, I think that’ll be more of an issue once we get into that, because people have very strong opinions about whether your app model should be immutable, you know, and whether you’re creating a new– that’s how redux works, right? Your app state doesn’t change The actual object doesn’t change MATT: That’s true But by default, with built_value, all the values that you create through built_value are going to be immutable by default So every time you want to permutate on an object or you want to change the values internally, what it actually will do is it will generate a new one for you One of the benefits of built_value is that if you build multiple objects with the same internal state, it will not generate multiple objects like when you reference one And it will give you– ANDREW: Interesting MATT: –things like object equality and whatnot pretty much out of the box So there’s a bunch of useful attributes of using built_value you get just above and beyond the additional serialization piece too ANDREW: Which is good, because if you just want serialization, JSON serializable does a pretty– MATT: Yeah ANDREW: –crackerjack job at it MATT: Yeah, for small things built_value might be overkill But if you’ve got a large app, and you’re going to be generating a ton of objects, some of which may be represented to be the same, then built_value might get you some neat service ANDREW: Good I’m kind of guessing on some of these types I’ve got to be honest MATT: There’s a lot of– that’s a lot of parameters ANDREW: Mm-hmm Well, you know these are your fields Everything’s an item, so it has to be able to– oh, time to use a built collection MATT: We’re going to have to do some additional work for built collection ANDREW: [LAUGHS] So this would be a built list, integers, which I need to go up here And I think we touched a little bit about this last time as well

built_value is for single objects It does have a related package called built collection, which I hope we have in our package Yeah, we do So that’s already been imported using– that’s not how you spell that So we’ve already got that if I pull up the pub spec I think we pulled that in Yeah, so we already we’re pulling that one in last time Let me just make this bigger, so that normal human beings can read it So we’ve already got that package imported Right now, I’m just adding it to this file and importing it here So arrays, of course, are by nature immutable So if you just have a getter for a list, you could still conceivably mutate the list unless you have an immutable list object MATT: True And built lists are immutable list objects– ANDREW: Right MATT: –I believe ANDREW: And so, that, I believe, also needs to be a get All right MATT: So many getters ANDREW: I know MATT: Nice thing is is built_value will just create the constructors for you ANDREW: It’s really driving home the point of me not wanting to write that deserialization method myself Parts? What the heck is parts? A list of related poll options in display order I’m going to go ahead and call that A built list of IDs basically I hope that’s the case The fun part is since you’ll be coding the live network calls, I get to do all this And then if it’s wrong, it’ll blow up when you try to use it and I’m sitting over there, which will be great MATT: I’m really glad I joined in in this episode ANDREW: [LAUGHS] And– MATT: When’s Phil coming back? ANDREW: Yeah, he’s coming back He’s hiding in the back somewhere Descendants is an integer, I think Yeah This kind of bums me out They have all these examples of the field, but they don’t have one that’s every single field, you know? Like, there’s descendents– OK, that’s an int MATT: Well, worst case scenario, we can leave a couple of these out ANDREW: Yeah Lord knows we’ve never made a mistake during an episode of The Boring Show MATT: Well, that’s what I was told ANDREW: Yeah MATT: Sorry You know, I meant I watched them all ANDREW: [LAUGHS] OK, so those are all my fields I should be able to save this and get an error for something Oh, because I just broke the part file MATT: Yeah, you’re going to have to regenerate that ANDREW: So let me go, and where am I? Let’s do– can I do this from memory? MATT: Huh ANDREW: I think that’s it MATT: Isn’t it pub run builder build? ANDREW: Ah I don’t get why they build, dang it It is a build task, isn’t it? I was so ready to flex after that No MATT: I think the other one might be build There you go One of these permutations will work– ANDREW: Yeah MATT: –at some point ANDREW: There we go MATT: There you go ANDREW: Assuming this actually works MATT: Yeah, that’s true ANDREW: So now we’re regenerating that part file MATT: Mm-hmm ANDREW: This is the generated source to match the properties that you just saw me drop in That’s the magic of built_value Let’s go back here, and I’ve got all kinds of little properties in here And I bet you if I scroll down, there’s my constructor, all kinds of stuff in here, equality I would love to know how this hash code function works [LAUGHS] There’s the to string Cool So built_value has just updated some stuff for me So let’s try running one of these as a test and see how that works Let me go ahead– I have this running Let me go ahead and stop it And I’m going to pop out to Hacker News and just try and grab one of these random– MATT: Oh You’ve got your serializers put into your built_value? ANDREW: It should be Well, that’s a good point Do I need a serializers file? MATT: Yes ANDREW: OK MATT: And you– ANDREW: Let’s go look at the example MATT: Mm-hmm There is a really good series of articles in Medium on built_value and serializing ANDREW: Is perhaps this what you referring to? This is the one that David– MATT: Which– yup, they’re the ones I highly recommend you read all of those multiple times, because I did in order to understand built_value ANDREW: Yeah, and you can get to them right from the GitHub repo, I believe MATT: Oh, they linked them through ANDREW: I believe he actually links them right in I want to– oh, no They’re on the pub They’re in his pub entry then So you can definitely find– oh, no, articles There they are Yeah, totally worth reading if you’re

going to do any kind of serious passing data on the wire with JSON MATT: The other thing that I found super helpful here is just that the built_value has the examples folder And if you check out both serializers and values, there’s a bunch of very simple examples Well, ranging from simple to mind blowing, but that’s what got me started when I was first playing around with built_value ANDREW: All right, I’m going to drop another file in here that I’m going to call serializers, which I can never spell on the first try And I’ll add that later So I’m going to drop in This is his example, which I’m about to trim the heck down, because I don’t have these classes MATT: Yeah, you’re just going to need the one, right? ANDREW: Yeah And this will be coming out of– what is it? JSON parse? We’re going to have to restructure some of this code in a bit as well There we go I’ll be closing that Let me save that And I also need the JSON plugin Here, we were talking about this the other day MATT: Yeah So one of the things that happens when you use the out-of-the-box serializer is that it’s going to serialize it in a weird list-like format where each tuple in the list or each two pieces are going to be a name and a value So it’s not going to really look like JSON Fortunately, there’s a JSON plugin, which basically makes it format nicely, where you have the JSON name-value structure by default. And so, highly recommended unless you’re doing some very bespoke managing of your data to use the JSON plugin ANDREW: Yeah The format that they use by default, it does have advantages Like, you can not have– put some type information on the wire, I think, in a way that– you know, normally, if you’re doing JSON, you sort of have to have agreement of what things look like completely on both ends And that’s how it works All right, what did I just copy out here again? There we go MATT: Oh, you need to plug– you need to add the plugin to your serializer creator, I think ANDREW: Oh my goodness OK, file serializers.to_builder MATT: Yeah, I think it’s the add_plugin that you can latch on to your builder ANDREW: There we go That’s what I’m looking for MATT: There you go That should do it ANDREW: OK And so, that’s– OK, so I’ve got another part file here The serializers file has its own part file just like the article one did So let’s go back to the terminal I don’t have to guess for this anymore since it’s the most recent command It’s very easy to write There we go So this should generate that part file for us– MATT: And there will now be– ANDREW: –if I come back in here MATT: –much generated source code Wow ANDREW: There we go MATT: Very little generated source code ANDREW: Yeah, that’s very small And I’m guessing I need to pull this package MATT: Yeah ANDREW: Sorry There we go MATT: That’s the one ANDREW: All my little red lines went away MATT: There you go ANDREW: That’s awesome MATT: Oh, look, you’re using new How very Dart man of you ANDREW: [LAUGHS] There you go It’s my own fault for cutting and pasting code that’s more than two months old OK, so let’s pop back here And I’ve got that, so I’ve got the serializers I’m not using dark convert just now I do need to include the file that I just made MATT: Mm-hmm ANDREW: And I’m trying to get it to where I can use this in a test just to make sure it works, because that’s what we were doing in our last episode So let’s go back to parse article MATT: So there’s a lot that’s involved here in terms of creating serializers and part files and everything else But ultimately, when you look at the amount of code that you’re writing for what you’re going to get out of it, I’m assuming this is going to be worth it, right? ANDREW: OK, abstract class article I’d have forgotten how to deserialize with built_value One second MATT: There was a serializer.deserialize ANDREW: That’s it And you give it the right– MATT: [INAUDIBLE] serializer ANDREW: That’s it so I should have serializers.deserialize with– MATT: Yup ANDREW: –article.serializer And I just realized I’m missing a line from my article class that I should not be So one of the things I need to do is– MATT: You need to pop a serializer– ANDREW: Yeah, this MATT: Yeah, there you go ANDREW: So each class reports that type of serializer

to use to deserialize it with built_value And so, I need to add And David Morgan once reviewed my code and told me to put it at the top MATT: Oh ANDREW: So I have it on good authority MATT: So the creator of built_value– ANDREW: Told me where to put certain– MATT: Your serializer ANDREW: Yeah MATT: How rude ANDREW: There we go And why don’t I find you or you? Is this capitalized? No MATT: Do they have to be generated? ANDREW: Oh, I may need to generate it again You’re right MATT: Yeah This is the thing with built_value You get a lot of red lines until you run the generator ANDREW: That’s why it can be a good idea to run the launch MATT: Yeah ANDREW: Which I’m not doing here just because I want to show each time it’s running But I think we covered that last time You could run it with a parameter to get it to just watch the file system and then kick off a rebuild MATT: Just be careful– ANDREW: Oh MATT: –your hot rebuild– ANDREW: We messed up MATT: –when that– oh, w hat happened there? ANDREW: Yup, declare OK, so this is the– see, it just gave me the right statement to use Such nice people It’s, like, hey, you’re parsing your code, and we noticed it sucked [LAUGHS] Let’s try that again Oh MATT: There we go ANDREW: Ah, I love mature libraries OK, that still needs a parentheses on the end, I think And I’m missing something here MATT: You need to import the serializer class ANDREW: Yeah, that’s what I’m wondering MATT: Yeah ANDREW: It must be a– there we go Cool MATT: Sweet ANDREW: One step at a time OK, now I think I can do serializer here I’m going to give it the object to be serialized, which, in this case, would be the parsed JSON MATT: Mm-hmm ANDREW: So just like before, we were parsing the JSON into a– it comes out as a dynamic, but it would either be a list under the hood of IDs– that was one of the examples we were doing– or it would be a map of key-value pairs And that internal format of the map is the same thing that build-value will take I’m not giving it the raw string And hopefully, this will work, I think [INAUDIBLE] Why aren’t you working– MATT: Oh, you got built list Yeah, that’s probably going to confuse matters slightly ANDREW: Do I need– doing something wrong MATT: Let me see if I can find something out ANDREW: Let me put– maybe I– if I import built collection up here? MATT: There we go ANDREW: I think that will get picked up in the part file Cool, OK So I was just missing that import for built collection, which was confusing the poor little serializer, because, of course, it has to deserialize a built collection So let’s go ahead and run this test now that I think I’ve got all the statically grabbable errors here There we go Is that going to break? There we are Do a reformat Let’s run– can I run you as a test? Oh, this isn’t my test file, is it? That’s why I can’t run it MATT: Oh, you’ve got your– ANDREW: That’s my JSON file MATT: Oh, that’s a neat way of doing it ANDREW: OK OK MATT: So you have that in a test You’ve got your JSON string And then you’re just calling the parser ANDREW: Yup, and this was– I’m trying to remember if this is the real one or if this is the hacked up one we were working with earlier Let’s wing it MATT: Let’s just cut and paste it up into a multi-line string Might make it easier to read ANDREW: [INAUDIBLE] Oh, deserialization error, OK MATT: Yeah, it’s not happy ANDREW: Internal link to hash map OK, and I’m going to stop this and back out I’m also going to make this bigger Let me go make– let me go get a– MATT: I can’t remember with built_value Are all of those parameters required?

Or do you mark them as required or– ANDREW: Oh, that’s a good point MATT: Some of them might not be there ANDREW: I think technically all of these are nullable Let me go back then and start putting some nullable on these And that, of course, has its own– is that kind of meta? Where do you get them? MATT: Let me see ANDREW: And it can’t come out of Flutter It’s got to come out of Dart MATT: Is it part of meta package? ANDREW: Annotations Can we go steal from the example again? Meta, so it is pulling in meta MATT: It still doesn’t like that ANDREW: Because it’s lowercase There we go MATT: Perfect ANDREW: I think that’ll do it Let me go real quick, do source gen again to make sure this is working So the built list will be nullable by default, because it’s a collection MATT: Mm-hmm ANDREW: But the primitives do need to actually update, OK OK, let me go back, start closing some things And actually, type should always be there By, I think, should always be there as well Time I don’t think poll options get scores Descendants can be null, OK Let’s try this MATT: I can see now why you want to do the watch file ANDREW: I do like knowing that it’s running I made a little button for it in Intellij to actually do that MATT: Oh, that’s cool ANDREW: OK, let’s go back down to JSON test, and let’s run this one It’ll probably still fail MATT: Oh, ye of little faith ANDREW: All right MATT: Internal linked– what is it? ANDREW: Internal linked hashmap MATT: Do you have the hash map inside your JSON, or do you have a map? ANDREW: I shouldn’t have any of this, but– MATT: Yeah ANDREW: Well, let’s break it out Dynamic Oh, I’m not parsing the JSON string MATT: You’re parsing a regular string, aren’t you? ANDREW: I’m just throwing a string at it MATT: You forgot the JSON– yeah, you should be encoding your JSON ANDREW: Point for me, all right I have to write– MATT: You could’ve discovered this 45 minutes– ANDREW: I know MATT: –later That would’ve been riveting watching on YouTube ANDREW: Just got done talking about how you need to parse the string first OK, so dynamic– [LAUGHS] MATT: Yeah, that’s– ANDREW: –equals– so we’ve got– are we doing it in here? Is that where– oh wait, we are decoding it in here MATT: Partial article? ANDREW: OK, hold on A week between filmings and I forget my entire life OK OK, got a break point in there Let’s rerun this with debug on and see where I’ve gone horribly awry MATT: You know, one of the other things we could do is comment out a bunch of those fields and just make sure it’s working on a few of them, because it’ll ignore the rest of them in the JSON object

ANDREW: OK, there we go So let’s step over that So what is actually in this data? Just a little bit of [INAUDIBLE] MATT: Now it’s going to– it’s a map of a whole bunch of strings to other things ANDREW: So by is a string, right? MATT: Kits is a group of a list ANDREW: Which it should be That’s one of my collections MATT: Yeah ANDREW: Descendants is an int All right, there’s ID as an int Where’s descendants? Yeah, descendants is an int Score is an int Time is an int, which I assume can hold a value that big MATT: Mm-hmm ANDREW: Title is a string Type is also a string, even though it should really be an enum, but that’s something to fix later And nullable is a– and a nullable string for the URL MATT: I’m wondering if it’s the built collection, whether we have to do something funky to make sure that that works ANDREW: Oh, I’m using the wrong serializer That is the standard list-based serializer, I think And this one is the one with the plugin MATT: Oh, you’re calling the wrong serializer You’re trying to serialize– ANDREW: Using the normal format MATT: Yeah ANDREW: OK MATT: So rule of thumb is don’t have two serializers in your serializer– ANDREW: Which I will fix in two shakes as soon as I verify this works All right, stop, save Let us rerun our tests, OK? MATT: I like the way that you have deliberately made all of these new mistakes with built list just to show everybody what– ANDREW: It’s a kindness, yeah Just like how I deliberately don’t prepare for these episodes just to show everybody everything, you know? That’s kind of my method All right, let’s step over that one Can we step over this one? We can MATT: Did that work? ANDREW: I think it worked We got a built list, information– MATT: Oh, you’ve got a built list ANDREW: My key promoter, which is normally a handy plugin that I’ve been running OK, so let’s take a second, see what we’ve got here So we now have an article class that is implementing built_values interfaces correctly We have a source gen’d version of it Look at that Nullable was in there the whole time It wasn’t even in a package So we have an immutable article object now that we can populate from parse to JSON that we can get from the network And so, I think– do you want to take a break here and swap? And then you can kind of take this And we’re going to tear out some things There were some mocks that got us to– MATT: OK ANDREW: That’s not even running anymore The version of this that we had going from the first episode, there were some mocks involved And so, those would need to be ripped out, and this real article put it in there MATT: But you don’t have any– you have no networking code yet, right? ANDREW: No networking code at all MATT: So do we want to build some tests around the networking code? I know they’re not really tests that you would want to run, because they require a network But at least they would get us going Or do we want to dive straight in and jump straight into the networking side? ANDREW: That’s a good question I think it would be good to just show at least one call– MATT: Yeah ANDREW: –to go get some JSON And we could still do that in a test, too MATT: Yes, why don’t we start with a test that actually pulls the JSON back from Hacker News? And then we can see it populating here And at least then we know things are working ANDREW: Yes MATT: Is it going to return a single article or multiple articles? ANDREW: So that’s the fun of the API It returns a list of IDs So this will be kind of fun It returns a list of IDs that you can get the top– MATT: Oh ANDREW: –500 And then you need to, one after another– MATT: Wait, I have to make individual– ANDREW: –by ID MATT: –network call by ID? ANDREW: Individual network calls MATT: Seriously? ANDREW: Yeah We’ll probably be talking about local storage and caching in our next episode MATT: Yeah We’ll be talking about not flooding the network ANDREW: Yeah MATT: OK, well, that makes life easier ANDREW: Mm-hmm OK, so– MATT: We’re not going to do a built value for a list of ints? ANDREW: No, no, I don’t think– MATT: No, that would be nuts ANDREW: That would just be a built collection– MATT: Yeah ANDREW: –anyway MATT: That would be overkill But for something with a dozen parameters, including internal lists of maps and everything else, built_value, once you remember to call the right serializer, is the way to go ANDREW: Yeah MATT: Yeah ANDREW: OK, so we’re going to switch places [SNAPS FINGERS] This is where we switch MATT: All right, that’s where we switch See, if Filip was here, that would’ve been super smooth But Filip isn’t here ANDREW: You really didn’t watch the second episode

all the way through, did you? [LAUGHS] I think I almost kicked over– MATT: I was coding while I was watching it At least, you know– ANDREW: All right, you’re busy MATT: Yeah ANDREW: All right And we’re back MATT: Ha-ha ANDREW: Can you hand me that sheet of paper down there? The one with writing on it? Because I want to talk about some stuff MATT: Is there a cheat sheet? ANDREW: There is a cheat sheet MATT: Oh OK, good ANDREW: Much like we crib code from other people’s examples There we go Yeah, so I thought this also be a good time– we talked in our last episode about how we’re going to respond to questions that people posted, which is great if I can keep myself from answering them too quickly in the YouTube comments, which is– it’s my instinct I see somebody ask a question It’s, like, oh, I can help with that And I’ll type out an answer, and it makes it slightly less fun to answer them here, a little bit less dramatic MATT: We’re going to be dramatic? ANDREW: Yeah MATT: Excellent ANDREW: But there are some– I actually learned something from one of the comments that somebody put down And hopefully, the graphics people can put it right about here in a second We talked about why there is no reflection in Flutter MATT: There is no reflection There is reflection in Dart, but not in Flutter ANDREW: And I kind of butchered the explanation for why And the– it does relate to the fact that the Dart is, ahead of time, compiled to native code But the detail that I left out is that Dart takes advantage of trees shaking So it can use– MATT: Oh ANDREW: –you know, delightful static language It’s strongly typed, statically dispatched, I think And so, we can go through and see which methods you’re actually going to use out of your codebase So if you pull in a package, you know, you only use two methods out of it, it can go in there and just toss out all the code that you’re never going to call, which is great until you try to use reflection to dynamically call one of those methods that’s now no longer in your app So that is the reason that reflection is out for the moment There is talk about bringing in some annotation-based stuff to tag things and say hey, I might call this with reflection later Don’t take it out when you do the tree shaking But as of right now, no reflection So thanks for that comment I actually, you know, got to dig in and learn something from it What else did we have? We also had something– I don’t think this is going to come up today, but somebody mentioned HTTP overrides in Dart Have you ever used those? MATT: I have never used HTTP overrides in Dart ANDREW: It’s a way to short circuit the HTTP client library and say, run this code as if this object I’m going to give you is the HTTP client MATT: It’s like marking out the HTTP piece? ANDREW: Mm-hmm MATT: So you can just provide JSON directly from, I don’t know, shared preferences or something? ANDREW: Whatever you want to do, mm-hmm MATT: Oh, that’s cool ANDREW: So for testing, you know, it’s how you would build a little convenient fake HTTP client MATT: Is that with the Dart HTTP or the HTTP package? ANDREW: That’s a good– we could probably look it up real quick if you want want MATT: We should probably look it up ANDREW: Yeah MATT: Where’s your– oh, there we go ANDREW: Mm-hmm MATT: Dart HTTP override ANDREW: There you go MATT: It looks– ANDREW: I think if you look in HTTP client, you’ll see it on the left So if you– or am I used to the Flutter one, where we get all the rest of them? Not on there? MATT: Not that I could see, no ANDREW: OK, it does exist It’s not like the Snuffleupagus, I swear It’s definitely in there Cool, OK So– MATT: Right ANDREW: Let’s get back to some things MATT: Great, IntelliJ I use Visual Studio Code, so– ANDREW: Yeah, I know MATT: –this is going to be fun ANDREW: Filip uses Android Studio MATT: So we’re going to have some interesting coding, OK So how does this work? We have this, and you have your tests in json_test.dart ANDREW: Mm-hmm MATT: So conceivably, I can create a new test, right? ANDREW: Mm-hmm MATT: That is going to do something like parses item.json over a network And so, right, what are we going to do? We’re going to not want to have this anymore So we can– ANDREW: Yeah, we’re going to go get the real business MATT: And we are going to have– so you use const I typically use things like final for mine, which I prefer much less If I’m going to have a URL in here– ANDREW: I think Filip wrote that one [LAUGHS] MATT: OK, all right We’re going to use final ANDREW: Actually, real quick, I ran into an interesting discussion with some of the tools team when we were talking to them this past week about how constants– if you change a constant, they said that will get reloaded for a hot reload, but a final will not MATT: Oh, it’ll rebuild the constants? ANDREW: Because that’s– so it’s a stateful– MATT: Oh ANDREW: –hot reload, so it wants to keep track of the state of your object And so, that includes any final variables that you’ve set at that point But constants aren’t considered part of that state And so, apparently, if you set a const on a variable, hot reload will update that If you’re setting const somewhere, and you want to see the effect of them, it will update that for a hot reload But a final, it’ll be like, oh, that’s app state

I’m stateful, so I’m not– MATT: Interesting ANDREW: –going to overwrite that MATT: I’m going to have to try that out ANDREW: Probably doesn’t matter for a test, but it’s an interesting bit of trivia that I came across, and I wanted to share it, too MATT: OK, so where’s my Hacker News API docs? ANDREW: That would be– we had them just a second ago I think maybe you overwrote them with that one MATT: Hacker News– ANDREW: Yeah MATT: –API There we go ANDREW: I think this it’s just an open endpoint MATT: OK, so let’s have a look and see how this works So we have– OK, so there’s a prefix So let’s just get that in SO URL prefix And I’m not going to be super clever and build these with nice URL builders I’m just going to go straight for the string and be done with it for the beginning So you said that there is a way of getting IDs ANDREW: Mm-hmm, so it’s– MATT: Where is this? Is it this? ANDREW: Down a little bit more No, top There it is MATT: Top stories, OK So we are going to start by getting top stories No, we’re going to get best stories, because they’re better than the top stories, because they’re the best All right ANDREW: I don’t know if best is best all time or what MATT: Bestest– ANDREW: I think– MATT: –stories ever ANDREW: –there might be a json on the end of that I don’t know MATT: You know what we can do? We can– ANDREW: Now, we can always test MATT: Nice URLs I cannot create a new tab I can cut and paste like a normal person Oh ANDREW: [LAUGHS] MATT: I have broken Firebase ANDREW: No MATT: OK, let’s try it with .json ANDREW: There we go MATT: I think this is– because this is using the Firebase– ANDREW: API MATT: –standard database OK, there we go ANDREW: There we go MATT: OK I didn’t break Firebase, awesome So we need besteststoriesever.json, chase and that’s great OK, so what are we going to do next? So we’re going to have call HTTP So Dart has a built-in HTTP library ANDREW: Mm-hm MATT: It’s fine It’s really good But people have improved on it and have created a HTTP package, which, if we go take a look at the Dart pub packages, we shall see that usually it’s up near the top ANDREW: Yeah, one would imagine MATT: It’s probably one of the D package you will almost always include in, which gives you really nice things like basically giving you gets and posts really, really, really easily and returning things as a future as HTTP does This also is super useful if you want to stream data into your apps So if you actually want to get a stream of bytes and do some funky real-time parsing as the stream of bytes comes in, this also can support that I’m not going to get into that, because I don’t remember how it works But trust me, it is there somewhere So we’re going to do a couple of things One is, I think, weirdly– even though it’s not in our pub spec– ANDREW: Are you thinking it might be on– MATT: –it does– ANDREW: What just happened? MATT: –actually exist, because– ANDREW: Does something else depend on it? MATT: Flutter does So it’s in there with Flutter– ANDREW: Interesting MATT: –which is nice Don’t depend on versions that are– ANDREW: Yeah MATT: –in Flutter, because as much as version dependency, et cetera– ANDREW: Yeah, as much fun as implicit unversioned dependencies we should probably have– MATT: I pretty much remember that these are very low numbers But trust me, this is not super alpha software This is actually– this is actually used by everyone, and most of those people run the Dart team You’ll recognize those email addresses ANDREW: Oh yeah, there’s Kevin MATT: Yeah, and– ANDREW: He’s found errors in my code before He’s a nice guy MATT: Your code’s perfect ANDREW: [LAUGHS] Because it’s been reviewed MATT: Save And does this automatically– ANDREW: No, you’ve got to do a packages get MATT: Use get? OK Visual Studio Code does– OK No ID was here That’s fine [INAUDIBLE] things ANDREW: Did you do the get? MATT: There we go ANDREW: That also works MATT: Yay, OK ANDREW: When in doubt, the command line tools are always there MATT: Yes So we have our URL ANDREW: Mm-hmm MATT: And we are now going to fetch our things So I think we can just do http.get ANDREW: Mm-hmm MATT: This is going to take our URL out This is nice This is going to return us a future So I could do final response equals a weight That’s fine And then I can make this– ANDREW: Do we have to tag that as a async– MATT: Async, which is probably a better way of doing it Actually, with HTTP, using then leads to nice structures But because we’re going to do an expect at the end, it’s going to lead to– ANDREW: Yeah MATT: –anonymous function madness,

so let’s do it this way ANDREW: Mm-hmm MATT: So I’m just going to use my res there, which is fine So what do we have? OK, so probably I want to check if res.statusCode is usually do not equal to 200 Then we’re going to do some error checking You know what? This is just us doing a test ANDREW: Yeah MATT: So I’m just going to keep this nice and simple and not handle any errors And so, what’s this going to give us This is going to give us res.body This is JSON ANDREW: It should be just– do we have to decode that or anything like that? MATT: We’re going to have to encode it, because this is a string I don’t think it– ANDREW: We don’t get UTF-8 for free, right? Is there something we have to do to go from a byte stream to an actual string or– MATT: I think this will give us UTF-8 ANDREW: Oh, wow MATT: In a stream situation, you have to decode the bytes ANDREW: OK MATT: When you get the body, I– we’re going to find out in a second ANDREW: Yeah MATT: So we’re going to say this is res.body so– in final JSON string equals res.body And that’s going to be json.encode– ANDREW: Wait, I think parse article’s doing that If we go back and look at it, I think this is where I ran into trouble half an hour ago Command, click will do it for you MATT: Am I doing something wrong? ANDREW: No MATT: Oh, it’s because my code base is all broken ANDREW: OK Yay MATT: OK, perfect ANDREW: So I think it’s doing the decode, yeah MATT: It’s just a random string ANDREW: I just ran into an issue last time MATT: OK, let’s– we don’t need to do that, so we just need to do res.body ANDREW: Mm-hmm MATT: OK, so how do I run this– ANDREW: Wait a second MATT: Oh, wait Look at that ANDREW: [LAUGHS] So we’d forgotten that we’re getting the best stories list and not the articles You’re parsing an article with a– MATT: OK ANDREW: –list of items MATT: So my– yes, we now have a list of IDs So we’re going to do some manual JSON deconstruction ANDREW: There we go MATT: So we are going to do final– we’re going to ID list JSON equals– my naming is terrible json.decode And we are going to decode my res.body ANDREW: I may have pulled dart:convert out of the imports above MATT: Beg your pardon? ANDREW: I may have– I don’t think I have dart:convert in this file MATT: OK ANDREW: [INAUDIBLE] MATT: Import dart:convert gives me my JSON OK, so at this point, json.decode, it’s going to give us a dynamic But it’s going to be an iterable, because it’s a list, I think ANDREW: Mm-hmm MATT: So we should be fine I could do something a little more clever like this Not too sure if we need to do that here ANDREW: So that would get you a list of dynamic, right? MATT: I think that would convert that dynamic into a list But it would be– ANDREW: But then it would be a generic type that would be list– MATT: Of dynamic ANDREW: –of dynamic, OK MATT: So let’s not do anything too clever, because– ANDREW: Works for me MATT: I know what happens when we do clever things Don’t work And so, we’re going to do ID list JSON dot– we’re probably– you know, let’s just see if this is working So let’s do if– this is no longer JSON It’s just ID list ID list.length is– no, because we have lots of things like isnotempty ANDREW: Oh yeah, there’s isempty and isnotempty MATT: Yeah, it’s really handy Then what we can do is we can– oh, we’re going have to do a second network call Oh, this is going to get complicated, OK So this is good OK, bear with me We’re going to know have a final story URL, of course Are you a double quotes or single quotes person? ANDREW: I’m single now that I use Dart MATT: Yeah I used to do a lot of Python I’m a single quotes person myself ANDREW: Mm-hmm MATT: And this is going to be– let’s take a look at the network call, which is here Oh, OK So this should be nice We don’t need pretty printing ANDREW: Yeah MATT: We don’t need any of that sort of nonsense What we need is vo/item/id.json

So it’s v0/item And it’s going to be something.json ANDREW: String interpolation for the win MATT: And we’re going to really make this super ugly by doing idList.first Do you like that? ANDREW: There you go MATT: Is my code super readable now? ANDREW: Yeah MATT: Yeah OK, so what do we have now? So we have this, so now we can do final– what are we going to call this? We’re going to call this storyRes equals http.get, storyUrl That’s lovely ANDREW: Mm-hmm MATT: Going to have to do this too And then what we’re going to have is we’re going to hopefully have our– you know, just in case This is going to– ANDREW: Pop up in there MATT: –live here And then this is going to be res– no, no It’s going to be storyRes So that’s going to make two network calls come back We’re going to expect this, and we’re– well, that’s probably going be wrong now ANDREW: No, you can put, you know, ID is not equal to zero or something like that MATT: Well, we can run this with breakpoint and see if it works, right? ANDREW: Yeah MATT: OK ANDREW: Yeah, in the real world, of course, you’d want to use an HTTP override or some other mechanism to test everything, but– MATT: Yeah ANDREW: –the actual networking MATT: Yes, do not actually put your actual networking in your actual unit tests ANDREW: Yeah MATT: Well, you can ANDREW: Yeah, have a separate integration test file or something like that that you don’t mind waiting 45 seconds for it to complete And so– MATT: Sometimes these tests when you do async, you can actually– handy tip– where is it? Where’s my async? Is this in need of async? ANDREW: Yup MATT: Yes You have additional– how do I show the parameters of this? ANDREW: Oh, Command-P MATT: Command-P. Command-P ANDREW: If you’re– you’re outside the method now So if you went back to in between the brace and the– MATT: There? ANDREW: Yeah, I think that’ll work Try again MATT: Ah, there is a timeout, and that is very handy when you’re doing, you know, not networking, but if you’re– ANDREW: Yeah MATT: –listening for streams or you’re doing whatnot, that will save you some madness if things accidentally run in an infinite loop or whatnot So timeouts are handy when you’re doing async stuff Handy tip, which I learned the hard way Right, how do I run this? ANDREW: So we would want to go from main.dart here We want to pull that down and go back to the test files MATT: So I got my break point Got my main.dart– ANDREW: No, sorry Up here, where you’re pulling down the wrong configuration So go to parses item.json MATT: You added this as your configuration? ANDREW: I think Filip did a while back MATT: We’re blaming Filip for everything ANDREW: We– yeah, he gets a lot done, you know? MATT: He does ANDREW: And then you can go here and click that and do debug There we go MATT: All right, let’s see what– oh Oh, Flutter instance already running ANDREW: Yeah, well stop it and kill it, I guess, yeah MATT: There we go Are you dead? ANDREW: [INAUDIBLE] MATT: I will do that again So we go here, we go debug Now we’re running a Flutter instance Hang on a second Hang on Maybe I hit stop Oh, I’m going to try that again Yay ANDREW: There we go MATT: My terrible IntelliJ skills IntelliJ is awesome It’s been too long since I used it ANDREW: Oh, oh Things are happening So we– MATT: Oh, so we’ve got– OK, so if we look here, we’ve got res– we got ID list Oh, look at that So ID list is working– ANDREW: Lots of IDs MATT: –we’ve got lots of IDs, much IDs, so IDs Our story URL is pulling out the first one Awesome We have storyRes And where our– we get our bytes– ANDREW: That’s our bytes, which I don’t want to look at and– you could step into this MATT: Oh, yes ANDREW: So that would be– MATT: This one? ANDREW: That one MATT: Story– oh, where am I now? Oh, wow ANDREW: Yeah, it did that MATT: [INAUDIBLE] that one Did I get somewhere new? ANDREW: You’re back where you were MATT: Oh ANDREW: You can try stepping in again, and maybe that’ll be– there we go Now, you can do step over, which is just to the left of where you were MATT: This one? ANDREW: Yeah, one of these days I’ll memorize these key commands MATT: Well, you have I’m the one who’s asking ANDREW: Yeah, I memorize what the buttons look like That’s about– MATT: Oh, check it– ANDREW: –as elite MATT: And got to step down again So what do we have now? ANDREW: So parse a string MATT: But check out our– reduce the string We’ve got kids, we’ve got descendants ANDREW: So it hasn’t actually made the article yet That’ll be the next call MATT: Oh, look at that Why nobody ever wins the car at the mall ANDREW: Oh, I read that this morning

MATT: That’s the bestest story ever ANDREW: Mm-hmm It’s– no one wins the car It’s true It’s a good article MATT: That’s actually– that was almost if we’d planned to pull that article out It could’ve been something entirely inappropriate ANDREW: Yeah MATT: But we got lucky OK, so I can just– ANDREW: Wait, one more step over We’ve got to make the article MATT: One more step over? ANDREW: All right, article parts MATT: Oh, genius ANDREW: Boom MATT: Look at that It’s like– so in the space of– let’s have a look, a few lines of code, most of them me, you know, checking to see if things are pulled down, right? Making a call in Dart, in Flutter, is like that The nice, thing, though, is– I mean, coming obviously from Android development and whatnot, where you have to wrap these things in an async task and run them in a separate thread or whatnot, because Dart is asynchronous by default, you can just do http.get, await or [INAUDIBLE] and pull it down JSON decoding for simple structures, we had a list of ints that work quite nicely We I didn’t didn’t even have to cast that to anything else It knew that it was in a dribble, and it pulled it out And they were ints Actually, well, it doesn’t know if it’s an int or a string, because I just used it here And then we pulled the story URL And through the magic of– where’s your article parser? ANDREW: It’s in JSON parsing, which is what lets you know it really needs to be moved somewhere else MATT: Yeah No, where is your– is this it? Yeah And through basically the magic of built_value– we did have to do some boilerplate to define it But there is no JSON parsing in sight here, because it was over-generated And so, once you get past the defining this and defining your serializer, which was literally this, things were good So we have your article objects, or class We have your parsing handling really nicely And we now have a network ANDREW: Mm-hmm MATT: I mean, Filip would have got this done in 10 minutes We’ve been at this for a while ANDREW: Yeah Actually, let’s ask our off-camera producer How long have we been filming now? SPEAKER 3: 42 minutes ANDREW: 42 minutes? OK, so we’ve got some time Do you want to switch back real quick? MATT: Yup, let’s– ANDREW: OK MATT: –do magic 3D cut thing and switch back ANDREW: Here MATT: Oh, could fall off the chair ANDREW: I know They go up so high It’s like wearing a bustle in the 19th century MATT: Do you have experience for that? ANDREW: No MATT: OK ANDREW: It’s what I imagine it– you never imagine what a bustle would be like? SPEAKER 3: One second [INAUDIBLE] ANDREW: That’s fine All right There we go And we’re back MATT: Oops ANDREW: [LAUGHS] MATT: Now we’re back ANDREW: Yeah, so let me– so one thing I wanted to mention, and this is a bit of shameless self-promotion here, the Flutter team, we put together a new repo for some samples MATT: Oh ANDREW: And it’s not accepted right now, because they don’t have push or writing requests yet I got to talk to Ian about it, but I do have a pull request We have a JSON example that has gone through It’s actually what David Morgan and Kevin Moore– MATT: Oh, that’s using– ANDREW: –reviewed MATT: –their JSON serializer builder plugin Not plugin, package ANDREW: It’s deserializing the same set of strings using three different approaches So a roll-your-own dart:convert approach, a JSON-serializable approach That’s a library for JSON serialization And then also built_value MATT: Oh, cool ANDREW: And so, that will be in the Flutter/samples GitHub repo hopefully by the time this episode makes it into post-production and gets released MATT: How do you have nine stars when there’s nothing in the repo? ANDREW: People like me MATT: OK, true ANDREW: I’m naturally charming MATT: Just– ANDREW: And– no [LAUGHS] MATT: Your code is so awesome that it’s– ANDREW: No, I think– MATT: In anticipation they’re starring your repo ANDREW: No– MATT: I like that That’s good ANDREW: — I don’t think people even knew it was my repo, because it’s– I mean, it’s really not It belongs to Flutter team, who made it And, you know, I’m sure people saw it and were like, OK, they’ll eventually put something in there And we will be putting things in there So, this will be one of the examples that goes in And the idea is that you can look at three different ways to serialize JSON and see which one is right for you So I wanted to mention that And also, I think– because we’re a little over 40 minutes or so at this point, and to keep going right now, what do we need to do? So we’ve got a model MATT: Mm-hmm, so we’ve got the model We’ve got the back end pulling it down So how hard would it be to wire in the rather naive networking code that I’ve written and get that displaying an article in– ANDREW: In an actual app MATT: –the Flutter app

ANDREW: So let’s go look at the– MATT: I mean, we could just say for any article you click on, it shows the article that gets pulled over the network But– ANDREW: Mm-hmm So we’ve got– let’s see MATT: Look at all these news ANDREW: Yeah, I know MATT: It’s the new police ANDREW: Yeah, because the very first episode, I think we recorded way before it was released Not the case anymore We now have a lead time of about a week So yeah, let’s get rid of all these news, actually, all of that, through the magic of– does VS Code do this? Just out of curiosity MATT: It might do– ANDREW: I assume it does MATT: –but my VS Code-fu is clearly not as strong as your IntelliJ-fu, so– ANDREW: Let’s see if I’ve actually broken it– MATT: –I would doff my hat to you if I wasn’t wearing a beanie ANDREW: All right, let’s go back to main.dart Let’s get out of testing right now So this is the UI layer that Filip worked up in the very first episode Let me make this a little bit more readable here Hide this MATT: Nice ANDREW: A little bit too big in that area Yeah, so we have a basic app And he is pulling things out of this, which is just a hard-coded list of articles So– MATT: But where is it showing– is there an article page? ANDREW: There is build item, which is going– it’s using a list builder, I think? Yeah, a list view And the children are a map of– he’s just mapping the list of articles to a list of widgets, basically And it’s [INAUDIBLE]– MATT: So in an ideal world, what we probably want to do is we want to pull the articles We want to cache them somehow, so we’re not hammering the network ANDREW: Mm-hmm MATT: And then that– ANDREW: That gets into a heavyweight article about app state management, though MATT: Yeah, maybe not now Maybe we could just pull the article, and just– we could generate a list from it and show the same article multiple times ANDREW: Mm-hmm MATT: Or when we get down to showing the article itself, we could just override the article with a piece of networking-fu to inject the new article ANDREW: Mm-hmm, so let’s– OK So we’re definitely not going to want that anymore, articles So let me– I’m going to– MATT: You’re probably going to want to have two functions, one which is get ID list and get article So we can break those out of the test and pop them into the utils function or whatnot, whatever– whichever way you want to structure it ANDREW: Yeah, OK, I’m going to pull all this code out and put it into article And that will be our new model So I’ve commented out– for those of you who’ve been with us through all three episodes, I’m commenting out the original one And then I’m going to call this article.g.dart And– MATT: You’re going to have to do your serializer magic as well ANDREW: I’m going to comment that one out and this one, because we’re not going to be using that one anymore So I will need to– I guess serializers needs to move, doesn’t it? Let’s put that up here MATT: And you’ll probably need to– do you need to import the– yeah ANDREW: There we go MATT: Nice ANDREW: So we’re just doing a little shuffle now, and I just broke main [LAUGHTER] Because comments count never existed really in the first place That was a made-up field that we made And we’ll comment this out as well Write an IOU to this whole section of code And also, our tests are broken, so that’s fun Let’s comment those out as well MATT: Common practice when your tests break– ANDREW: Comment them out MATT: –comment them out ANDREW: Yeah, that works And then I think we can rerun built, rerun source gen, and we’ll get article.g.dart MATT: Yeah, and– ANDREW: So we’ll get the same article class MATT: Your serializer will rebuild to point to the right ANDREW: Or it could just blow up That’s also a possibility MATT: I’m sure it’ll be perfect ANDREW: Yeah [LAUGHS] MATT: That’s a new warning ANDREW: I see that Dart UI warning a lot I think that’s come up in other episodes MATT: Yeah, I think that’s because it’s a holdover from what they’re doing on the web side of things But you can ignore that one It has no bearing on what it produces ultimately ANDREW: Yeah Although, if you are a Dart coder for the web, built-value works just fine MATT: Yup ANDREW: It works on both MATT: This is one of those works across all platforms So– ANDREW: OK, so now we’ve got an article that’s is serializable, right? So we could now go back into main and say let’s use that somehow So we could– MATT: OK ANDREW: What if I just– what if I faked a list of IDs, say 10 IDs,

and I just put them in an array up here, and then we set up something that would– MATT: Well, why don’t you– didn’t we– ANDREW: –can fetch them somehow MATT: Can you go back into your console panel, because you could just steal all the IDs from that if it has– ANDREW: Oh, I was actually going to go back to your call MATT: Oh, we could just get it from the other web call ANDREW: Yeah MATT: That would have been simple I think it’s the next one over ANDREW: OK No– oh, there we go MATT: There you go ANDREW: So let me just steal some of these That looks like about 10, right? And we’ll go back And I’m just going to drop these Let’s change this to an int for right now MATT: Mm-hmm ANDREW: We’ll call it IDs MATT: Nice ANDREW: Let me get rid of that And this is going to– MATT: Auto-format ANDREW: Junk MATT: Dart format is great ANDREW: So now I got some IDs It would be– MATT: Oh, you’re going to do some clever mapping things, aren’t you? ANDREW: I’m going to– I’m wondering if I can map the IDs to future builders that will kick off the request and then parse the result MATT: So we’re going to create a function to do the HTTP networking stuff and return a future article ANDREW: Mm-hmm I’m also going to pull out the refresh indicator for right now Forgive me, Filip There it goes, OK MATT: Wait, I can hear– ANDREW: Yes MATT: –the sounds of screaming– ANDREW: Somewhere 12,000– MATT: –in the distance ANDREW: –miles away Filip– OK OK, so now I’ve got that I’ve got one too many of those, I think There we go So now I want to map the IDs This is going to be some serious functional programming here, probably more than I can really handle MATT: Oh, this is going to return a list of futures But that’s kind of OK, I think I think you can probably handle this ANDREW: Let’s just make sure I’m doing this right Always good to have the right of our parentheses, OK MATT: So that should work now and just– ANDREW: Yeah, this is going to produce a bunch of ugly text widgets– MATT: Yeah ANDREW: –I think So let’s go ahead and through the magic of hot reload, there they are MATT: Oh, look at that, it’s still– it’s running this whole time ANDREW: Yeah MATT: I didn’t actually kill it when I hit stop, OK So the problem here is just that we’re going to map this, but it’s going to map to a– it’s going to map to a bunch of futures There is a way of saying don’t return the map iterable until all the futures are futured up I just wish I could remember how to do it ANDREW: Well, I was wondering if we could do it with FutureBuilder, because with FutureBuilder, we could just make the request to give it the future that comes off of that MATT: Well, if we passed the– so if we– yeah, we could do, actually So if we– oh This is it This is hardcore ANDREW: We’re going to do a widget, right? MATT: So FutureBuilder is going to return a widget You’re going to have to give it a future, oh, and a builder ANDREW: This would be a widget builder, which is what? Just build context? MATT: It’d be build context And it would be async task of type widget ANDREW: Let’s just look at FutureBuilder real quick Again, one of the best parts about Flutter, all open source You can always go look at the docs [LAUGHS] MATT: Yeah Although– yup ANDREW: So it takes a future, an initial data, and a builder And the builder is– MATT: Builder– ANDREW: –async widget builder– MATT: Yeah ANDREW: –typed, which is build context and a snapshot MATT: Of a certain type ANDREW: OK, this is getting slightly more complicated than I hoped it would be But let’s see what I can do MATT: No way, we’re good ANDREW: All right, so this would be– MATT: This would be– ANDREW: –this build context MATT: –build context ANDREW: And then a MATT: Async snapshot ANDREW: –article Async snapshot of an article, right? MATT: An async– well, you’re returning ultimately a widget, right? ANDREW: Let’s just say null for now Why are you yelling at me? What have I forgotten? MATT: Because you’ve got Widget in FutureBuilder It has to be the same type ANDREW: Oh, of course There we go And that’s going to be a big function So let me just go ahead and make it what we’re at now So we are– and then we need a future, right? MATT: Yeah, we need a future ANDREW: Future is– MATT: You know, we could just do HTTP– oh no

ANDREW: Because we need to parse some stuff MATT: Because we’ll need to parse some stuff, so we might want to have– why don’t we have a function– why don’t we create a function that returns a future, and then just pop the– ANDREW: So it would take an ID– MATT: [INAUDIBLE] ANDREW: –it would return to a future article Does that makes sense? MATT: Yup ANDREW: So future article, get article And that will take an ID And so I would– let me go look at the test that we just wrote to do this There we go MATT: So you only need the– you don’t need the first half You only need the bit with the pulls from the ID ANDREW: Right there MATT: There you go ANDREW: Cool I’m going to go back into main, boop OK MATT: Well, it’s all good You have to make– ANDREW: And that becomes ID, which means we don’t need the brackets, which is fun, right? MATT: Yeah And you’ll need to make that async ANDREW: Async MATT: And– ANDREW: And we need to import HTTP MATT: Mm-hmm And then it’s usually HTTP as HTTP– ANDREW: That’s right MATT: –so you don’t have weird GET– ANDREW: Instead of polluting– MATT: –methods all over the place ANDREW: It’s the global get method MATT: That’s good ANDREW: It’s fine A story URL if a story– oh I think that was wrong on the original test MATT: Oh, it’s like you said my code was wrong ANDREW: Still worked storyRed is definitely not this little Freudian slip there OK MATT: And you want to return the parsed article OK ANDREW: That seems suspiciously easy, OK So that would be getArticle for i, like that MATT: Mm-hmm ANDREW: And so, here we might have data We might not, right? MATT: So this is basically– the builder has to return the widget tree ANDREW: OK MATT: So you probably want to return build item article ANDREW: Let’s just two texts for right now until we get– know that we’re– MATT: I believe in your code ANDREW: Yeah MATT: I believe in your code OK, let’s just do that ANDREW: I don’t But we’ve got to check to see if the snapshot has data, right? MATT: Yes ANDREW: OK MATT: So one of the things when you’re using FutureBuilder is– ANDREW: I’m going to change that to snapshot, by the way MATT: FutureBuilder has a– snapshot has connection Oh, that’s an interesting way of doing it ANDREW: Oh, is this not how you– MATT: I do it differently ANDREW: How do you do it, actually? MATT: So if you do if snapshot.connectionState– ANDREW: connectionState MATT: –equals equals ConnectionState– ANDREW: Some enum value MATT: Yeah, dot done There’s a whole bunch of them in there, but done means the future is finished ANDREW: Interesting MATT: And then for anything else, I usually then just show a circle progress indicator to show that you’re waiting And by the magic of Flutter, it just will show the circle progress indicator until the future’s complete, and then boom ANDREW: And then the future updates, OK MATT: You don’t like circle progress indicator? ANDREW: I like text It’s like the console debugging of the Flutter widget land MATT: Alert Let’s just use alerts ANDREW: [LAUGHS] Alert [INAUDIBLE] MATT: If there’s not an alert widget, I’m going to write an alert widget just for you ANDREW: You should have seen me when I was doing C++ stuff, I would be– like 20 printf’s was my debugging method, because it’s all– MATT: Join us as we reminisce– ANDREW: Yeah MATT: –down memory lane and how we use print statements to debug our code ANDREW: Join us next week on code done badly– MATT: Flutter– ANDREW: –in the past MATT: –the advanced way of writing mobile apps via text ANDREW: [LAUGHS] All right, Text, article, dot– MATT: Name? Title? ANDREW: Oh, wait snapshot article– MATT: Oh yes, it’s going to be snapshot.data, dot title? Name? It should pick up the type ANDREW: Oh, oh MATT: Oh, there you go ANDREW: That’s right MATT: There you go ANDREW: Let’s do title and I should probably put returns on this MATT: Yes ANDREW: Because it’s good to have functions return things when they have return types I almost don’t want to do this MATT: I– yeah, I’m curious [GASPS] Did that just work? ANDREW: Holy crap MATT: Oh no– oh, there we go That did work I hope they’re all OK ANDREW: Let me pull up padding on here Now that it works, let’s add a little padding, yeah MATT: Can you put in my circle progress indicator now, please? ANDREW: OK, so it’s a widget Again, it’s something I’ve never used So circle– MATT: Circular ANDREW: Circular MATT: ProgressIndicator ANDREW: You’ll find my IQ is normal MATT: And that’s it ANDREW: Oh, just like that? MATT: And let’s see Watch Oh Now, the problem there is that because we’re doing it inside the map, it’s going to do one for each, which, you know,

we can fix, but you’ll probably need to center that, because otherwise it’s going to take up the full thing That’s why they all look weird ANDREW: OK MATT: So if you wrap that in a circle– ANDREW: Wrap with widget MATT: Center, I beg your pardon ANDREW: Oh wait, center has its own thing MATT: Yup ANDREW: There we go MATT: So let’s see if that does something There you go, OK ANDREW: I can’t believe that worked MATT: Complete faith So you– ANDREW: Now we can use build item MATT: Yeah ANDREW: So OK– so what did we have to– comments We still have a comment count, because that’s– I think we covered this in another episode It’s actually hard to calculate But we could do type MATT: This is a row, and you’re going to– OK, sure And you’ve got an icon button for launching the URL That’s cool ANDREW: OK, so we’ll do the article type And then, well, we were doing a fake URL before So let me go ahead and get a real article OK, my least favorite bug currently in the IntelliJ plugin, which is fixed in the new release, by the way MATT: Oh ANDREW: By the time this makes YouTube, that might already be fixed There’s a weird thing when you do tab, it replaces too much MATT: Might want to be careful, because you’ve got the URL in two places You’ve got fakeUrl and article.url ANDREW: Yeah, I’m going to get rid of fakeUrl and just– MATT: Yeah, we don’t like no fake URLs ANDREW: There we go All right, and then this would become build item snapshot.data Oh [CLAPS] MATT: Data not equal to null ANDREW: Is that in text? I often do this OK, so texting is getting– oh, OK MATT: That’s article.text It’s article.title? ANDREW: Title should be article dot– oh, because some of these might not be– interesting OK, so I’ll just do this for now thanks to the magic of the coalesce operator MATT: But isn’t it article.title or article.text? ANDREW: I think it’s [INAUDIBLE],, so I could check our– MATT: Oh, we had text, which is– ANDREW: Oh, no, no, you’re right MATT: –which is the comment or story, and title is the thing So I think they all had titles– ANDREW: Yeah MATT: –because you were displaying them earlier ANDREW: You’re right It should be title anyway So I’ll leave the null coalesce in there and just switch that to title MATT: And your key, you might want to change just in case your keys get messed up ANDREW: Oh yeah, I’m sure that’s not– MATT: That’s a thing, what happens with lists ANDREW: Yeah Oh MATT: Oh, is that going to work? Is that going to click through? And are we going to be able to read why nobody buys things in the mall? ANDREW: Is it loading? MATT: I think it’s loading It’s loading something ANDREW: Did we use some weird proxy setting on it? Some weird proxy on the simulator? MATT: Can you build things from the emulator? ANDREW: I should be able to MATT: Well, try another one ANDREW: I mean, I’m loading things from this MATT: It might just be– might be the– might be the site URL That’s The Guardian Surely, The Guardian works ANDREW: There we go MATT: Yay ANDREW: And less plastic trash That’s nice MATT: Your app’s done ANDREW: Holy crap MATT: You’re finished ANDREW: Yeah, we’re done MATT: Yeah ANDREW: End of series MATT: Yeah ANDREW: Yeah MATT: Thanks for joining ANDREW: All right MATT: Hey, Filip, we’re really sorry– ANDREW: Yeah MATT: –but you missed the end of the show ANDREW: We solved it all MATT: Yeah ANDREW: All right This seems like a natural stopping point then for this episode MATT: I think we’re going to– we’ve chanced our luck enough ANDREW: Yeah, so things to reiterate, do please post comments and questions on the video You can also do #BoringShow on Twitter There are a few from there that we saw as well and tried to answer And we will be back I think I might not be in the next episode Maybe it’ll be you and Filip or– MATT: One of us ANDREW: –you and whoever we can drag down in here into the studio or something MATT: So one of us doesn’t exist ANDREW: Yeah MATT: Yeah At any point, one of us doesn’t exist ANDREW: Never see the same one again That’s nice MATT: So there will be a surprise lineup– ANDREW: Yeah MATT: –in the next show ANDREW: And yeah, give us some ideas about how you would like state management done, if you have a particular approach to it that you’d like to MATT: Oh, wait I have to turn up for the state management one? ANDREW: Yeah, it’s all you MATT: Oh, great ANDREW: You gave the talk at IO You’ll be fine Because there’s a bunch of options, and it seems like we don’t have to do that in the next video, but we might want to touch on it now that we’ve gotten some of these basics figured out So– MATT: We’re getting close ANDREW: You know, blocks, redux scoped model, It might be good to just roll our own inherited widget just to see it MATT: Yeah, or even just set state in places, but–

ANDREW: Yeah, or just, you know, stateful widgets They work pretty good MATT: Mm-hmm ANDREW: But yeah, I think that’s it MATT: Perfect ANDREW: Yeah, thanks for sticking with us MATT: See you later ANDREW: See you next time [MUSIC PLAYING]