Flutter's Search Support (The Boring Flutter Development Show, Ep. 10)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
ANDREW BROGDON: Hey, everybody. Welcome back to The Boring Show. I'm Andrew Brogdon from the Flutter team. And with me is-- MATT SULLIVAN: I'm Matt Sullivan, also, from the Flutter team. ANDREW BROGDON: Yeah. And so today we're going to pick up right where Phillip and Will left off. We're going to build on what they had done, and we're going to talk about adding searching to the app. MATT SULLIVAN: Oh, cool. So this is the Hacker News app that they built. ANDREW BROGDON: Yes. So we're going to be working on the Hacker News app. And right now it pulls down articles and puts in a list view, and you can expand them and use URL launcher to get out to the actual article. We're going to use some stuff out of the material package to add some easy searching functionality to the existing app. MATT SULLIVAN: Searching is never easy. ANDREW BROGDON: Well, now-- MATT SULLIVAN: You're going to prove me wrong. ANDREW BROGDON: Let's see. I think we can get this wired up pretty quick. It's-- MATT SULLIVAN: Cool. ANDREW BROGDON: It's a fairly straightforward thing to do. So if we look at the code, material has-- let me go into the API docs here. Material gives us this nice show search function. MATT SULLIVAN: This is going to be in the same vein as you have things like show persistence sheet, show modal dialogue. ANDREW BROGDON: Show modal dialogue is one I've used before, yeah. MATT SULLIVAN: So this is a conditional one. Show search. ANDREW BROGDON: Yeah. See, there's some top level functions just kind of hanging out in the material package that you can call. And so this is show search that I'm looking at right here. It takes a build context, because you're going to be displaying something, you need a context to put it into a tree. And it takes a search delegate. And a search delegate is a thing that does searching for you. So it provides kind of a nice framework to basically get the search functionality wired into the UI. And so let me go ahead, pop in here. Quick note, in keeping with Will's request at the end of our last episode, I did change the font. We changed the font from the sort of 1980s style to Garamond, which is a little bit more newsy. MATT SULLIVAN: So we actually have some like styling. ANDREW BROGDON: Yeah. We did a slight bit of styling before this episode in keeping with some requests from Will that he made. So it might look a little bit different, but it's just a font at this point. So we've got our app here. It uses-- it's got a home page, and we need to wire in searching. So we're going to need a search icon somewhere that people can click on to trigger it. And we're going to need this search delegates. Let me start-- let's drop an icon into our-- MATT SULLIVAN: Why don't we stick it in the app bar. ANDREW BROGDON: Stick it in the app bar. I think we can go up here and just do actions, right? MATT SULLIVAN: Yeah. One of the nice things about the floaters implementation of the app bar is it gives you a whole bunch of other widgets you can drop in. One of them is actions, which will basically display things, I believe, trailing at the end of the app bar. ANDREW BROGDON: Yeah. So we've got our Hacker News icon on the left. So we've got in the center our title, and this should go on the right. So let's do-- I'm guessing I need an icon here. MATT SULLIVAN: Do you want icon or icon button? ANDREW BROGDON: Let's see. I was going to go with an icon button. We could do a straight up like gesture detector and start with that. MATT SULLIVAN: Could do. ANDREW BROGDON: So we'd have an on tab and I'll just give it an empty one for now. And then child would be an icon. And so we give it-- I'm guessing-- yep, search. There's the Search icon. There we go. Put that in there. MATT SULLIVAN: Oh, and you can preview the icon over on the reference side. I never noticed that. ANDREW BROGDON: You can do that actually with material icons, not with the Cupertino icons, believe it or not. So we have an open bug for that. That's a request I made of the IntelliJ plugin team. Because I've been working on some Cupertino stuff. MATT SULLIVAN: Cool. ANDREW BROGDON: But, yeah, you get the little search thing right there. And so let's save that and see what we get. MATT SULLIVAN: There we go. ANDREW BROGDON: Cool. MATT SULLIVAN: You know, probably the problem here is that if you make that an icon button that will give it more appropriate padding. ANDREW BROGDON: All right. Let's try that. MATT SULLIVAN: Because just your texture's one way to get gestures on-- a whole range of gestures on any type of widget. Icon button will basically do most of the wiring up things like the InkWell splash and all the other bits and pieces for-- ANDREW BROGDON: That's right. All the other material eBits. And I think this takes an on press like that. NT yelling at me. What have I forgotten? Too many positional arguments? Like that? OK. MATT SULLIVAN: If you wanted to do double tap or long press on an icon, then you'd use gesture detector. But-- ANDREW BROGDON: Or dragging it, for some reason if you want. I don't know why you'd want to start a drag-- one of your actions but-- OK. So we got-- we got a-- can I click this? Yep. MATT SULLIVAN: Here we go. ANDREW BROGDON: There we go. OK. So now we got something we can launch our search with, which is cool. Let's get the search delegate in here. I'll put it-- let's just put it at the bottom. So class, article search. MATT SULLIVAN: Sounds good. ANDREW BROGDON: And I'm going to pass [INAUDIBLE] case this because that's how we do things. And then it's extends, search, delegates, which is a generic. And so you put in the thing that you want to get out of the search. MATT SULLIVAN: Yes. So what type you want to get out of the search. ANDREW BROGDON: Yeah. MATT SULLIVAN: So here we need to make a decision. So when we search for something, what do we want the action to be? ANDREW BROGDON: That's a good question. MATT SULLIVAN: Because what we could do is we could create a separate page, and we could have a details page. Probably the easier thing to begin with is if we search and get the URL, and then we can use the URL launcher to-- ANDREW BROGDON: See it pick a result and you just go immediately to the article just as a sort of demonstration of the concept. MATT SULLIVAN: But the problem with that, potentially, is when the search results come back, you're going to see the URL and not the title. Do we have the concept of an article class? ANDREW BROGDON: We do. MATT SULLIVAN: So maybe we could-- ANDREW BROGDON: Why don't we do-- MATT SULLIVAN: --return that? ANDREW BROGDON: --do an article and start with that. And so that's going to extend-- I'm just going to put a bunch of blank lines in here so I can kind of work in the middle of the screen. And so we're being yelled at because we're missing a whole bunch of required overrides. Boom. MATT SULLIVAN: Build actions, build leading, build results. ANDREW BROGDON: Right. So, yeah. MATT SULLIVAN: Build suggestions. ANDREW BROGDON: What the heck do these do? Fortunately, we have-- here. So we have-- this comes with four different build methods. Build actions so widgets to display after the search query in the app bar. So this is going to pop up a new screen on top of whatever we had before that's going to be our search. MATT SULLIVAN: So this is the equivalent of using the navigator to navigate to an entirely new widget tree inside the-- ANDREW BROGDON: Which it's probably doing under the hood. MATT SULLIVAN: It is because I think we're going to have to use Navigator.pop to get back off the page. ANDREW BROGDON: Yeah, that would make sense. Although, is there a-- oh, there's close method. MATT SULLIVAN: Or you could just use a close method. ANDREW BROGDON: OK. So build actions, build leading, which is the widget to display before the text that you're going to be typing into. So like a back button. MATT SULLIVAN: Yeah, it's going to-- yeah, there's going to be-- that's going to be the leading button on the left of the search bar. ANDREW BROGDON: So that's when we'll call close. MATT SULLIVAN: That's when we'll call for-- yeah, so if we want to have navigation back-- you know, those if you want to close, the easiest way to do that would be to either do the Cupertino little x in the corner, or to have the Android back arrow. ANDREW BROGDON: So just for fun, what if we just leave all those empty? I wonder if it'll completely freak out? So show search is the name of the function. Then I could just give it an article search object. And that should be-- what else have we got? Oh, you're right. Unfortunately, I have one because I'm in a builder. Take it those out of order. MATT SULLIVAN: You might have to-- ANDREW BROGDON: They're not positional. Search. Just delegate. Delegate. There we go. Now, I put my comma in here so I can format, which always makes me happy. Bring my same back up. MATT SULLIVAN: I feel bad things are about to happen. ANDREW BROGDON: Yes. MATT SULLIVAN: That just happen. ANDREW BROGDON: So it's not kidding when it says to do. You need to implement this. So-- MATT SULLIVAN: The question is, which ones are these is it going to need? ANDREW BROGDON: To get going we could go-- I wonder if we could find out where exactly it failed. Anyway, let's start putting some things in here. So build actions. So we would have a-- so that's to the right. So if you wanted like a clear-- or something like that. MATT SULLIVAN: This is the same as-- this is the same as the app bar. So you have actions on the right and you have leaving on the left. ANDREW BROGDON: That's why it takes a list. MATT SULLIVAN: So we could return an empty list and it might-- ANDREW BROGDON: Let's just give it some kind of an icon here. Is there a clear? Cool. OK. So that's one. Three to go. Build leading-- MATT SULLIVAN: Semicolon or a comma. There you go. ANDREW BROGDON: Gets me every time. There we go. MATT SULLIVAN: Don't you just love backseat drivers? [INAUDIBLE] ANDREW BROGDON: You're right, I can't-- you spotted an actual error so-- MATT SULLIVAN: You coded wrong. ANDREW BROGDON: --I can hardly complain. MATT SULLIVAN: So I can just-- you know. ANDREW BROGDON: You missed the exit two miles ago. MATT SULLIVAN: So this is a single widget. ANDREW BROGDON: Right. And so this is the build leading. So this is where we could return a button to close. MATT SULLIVAN: Yeah. ANDREW BROGDON: So we tried that. And that could be an icon button. Right. So that gets an icon. MATT SULLIVAN: See, it gives icon.clear or .left back. ANDREW BROGDON: Is there a row back? Like that. And then we need to give it an on pressed. And that-- oh, it was going to do closed, right? And close takes a-- MATT SULLIVAN: I think so. You need the context and closed-- ANDREW BROGDON: Oh, it gives me a context. OK. So I can use that. And-- MATT SULLIVAN: Wait. What does it give you? ANDREW BROGDON: Oh, this wants the result. So we pass back a no? MATT SULLIVAN: Let's have-- let's have a look. ANDREW BROGDON: Why don't we go-- let's look at the-- MATT SULLIVAN: Oh, OK. So let's press make null for the time being, because we don't have a result. ANDREW BROGDON: The return value provided for result is used as a return value of the call to show search. So if we want it, we had to pass something back to be like, hey, they didn't care about the search, right? MATT SULLIVAN: Yeah. So it could be an empty article that might just take null. ANDREW BROGDON: Yeah. I think null would work. Does this build now? No? All right. MATT SULLIVAN: How about we just ret-- we could return null for those two widgets. That might just be looking for the return. Child is not equal to null. Which child? ANDREW BROGDON: Let's just return a container. I'm worried that I've messed something else up and I just think that I've-- no. OK. So there's that. That still has-- let's make this an icon button, too. MATT SULLIVAN: Yeah. ANDREW BROGDON: So we give it an icon like that. Then we need an on pressed. Let's just give it an empty one for now. And capitalization helps because this is not Visual Basic. There we go. No offense to anyone who codes in Visual Basic. Gets a lot of work done. And what am I messing up here? That's it right there. MATT SULLIVAN: There you go. So does this mean if you click the leading, what happens when it calls close? It closes. ANDREW BROGDON: Did you see that, though? Watch. I swear I saw a little bit of the red screen in there the first time I did that. No. All right. MATT SULLIVAN: OK. We should-- we'll have to watch the re-- ANDREW BROGDON: I'm imagining things. MATT SULLIVAN: We'll watch the rerun and see-- ANDREW BROGDON: Yeah. MATT SULLIVAN: --what we messed up. ANDREW BROGDON: What are we-- are we 30-- are we 30 fps here-- MATT SULLIVAN: Comments below, please. ANDREW BROGDON: --for YouTube? I don't know. MATT SULLIVAN: We're surely recording this is 60 fps because that's what Flutter does, right? ANDREW BROGDON: I just moved so quickly you can't really get the nuance at 30 fps. MATT SULLIVAN: You're-- you're a blur. ANDREW BROGDON: Yeah. MATT SULLIVAN: So where were we? ANDREW BROGDON: Yeah. So we launched an empty screen, and then I congratulated myself a lot. MATT SULLIVAN: Search was typable now, right? ANDREW BROGDON: You should-- MATT SULLIVAN: Search bar. OK. ANDREW BROGDON: Curious why the soft keyboard didn't come up. All right. We'll have to look into that one. All right. So we have build results and build suggestions. So how do we get the current state of the search? MATT SULLIVAN: OK. Let's take a look-- ANDREW BROGDON: Let me-- MATT SULLIVAN: Let's take a look at-- ANDREW BROGDON: There's gotta be a way to do that. MATT SULLIVAN: API surface and see what we're given. There is-- there you go. There's a property called query. ANDREW BROGDON: Here we go. OK. So we can do-- MATT SULLIVAN: I guess it-- ANDREW BROGDON: So we'll have a query which represents whatever-- MATT SULLIVAN: Now, the question is-- ANDREW BROGDON: --people are typing in, so I should be able to do something like this. MATT SULLIVAN: Text query. ANDREW BROGDON: Maybe. MATT SULLIVAN: And then-- OK. ANDREW BROGDON: So pop up my search and do-- there we go. MATT SULLIVAN: Magics. ANDREW BROGDON: So we do have data. We've got to connect this to something. Oh, wait. That's a good point, too. So we have this little clear button not clearing anything. Is there a way to clear this? I bet there is a method for that. MATT SULLIVAN: And let's have a look. ANDREW BROGDON: Clear. Or do we just go-- can we assign to query, as well? Does that work? It apparently does. MATT SULLIVAN: Wow. ANDREW BROGDON: So now we're working clear button. Awesome. Thanks to the magic of string assignments. MATT SULLIVAN: Search and so we're going to have to-- so what do we-- we're going to have a list of articles to-- to-- this is almost like-- more like filtering the search. But I guess same thing. ANDREW BROGDON: Yeah, that's a good point. How do we get those into the search class? MATT SULLIVAN: Because this is a sort of-- it's navigated to a separate context. So, yeah, how are we going to do this? ANDREW BROGDON: So we have-- I mean, we have our block, right? That's where we get-- somewhere down here we're using a stream builder. MATT SULLIVAN: OK. So we can use this-- ANDREW BROGDON: So we have our block. MATT SULLIVAN: --stream builder. ANDREW BROGDON: We could give our-- all right. So this is-- so the list from-- so the body is a stream builder, which means when the block updates the stream, that's going to get rebuilt. Right. MATT SULLIVAN: So this is coming from block dot-- where is block coming from? It's coming from a-- ANDREW BROGDON: Block is given to us by the app, I believe, right there. So the app creates the block here. MATT SULLIVAN: OK, so is it up? ANDREW BROGDON: Yeah. There we go. There is where the block is created. MATT SULLIVAN: So we created-- ANDREW BROGDON: That's given to the app. The app drills it down into the home page. MATT SULLIVAN: Where do we insert it into the widget tree? ANDREW BROGDON: So it goes in right here as part of this, my home page. MATT SULLIVAN: OK. So when we call my home page-- ANDREW BROGDON: That's got a working block at that point. MATT SULLIVAN: The block. OK. ANDREW BROGDON: And so the home page state, which is the one building the search, that can do-- MATT SULLIVAN: So we don't actually-- ANDREW BROGDON: That could get-- that could get us the current state of-- see, if we're really slick, we'd like update the search cla-- the search delegate class with like the stream on the fly. I don't think we're quite there yet. We could give it-- MATT SULLIVAN: How many hours do we have for this-- ANDREW BROGDON: Yeah. This will be our first ever seven hour Boring Show episode. MATT SULLIVAN: Yes. ANDREW BROGDON: We could just give it as a parameter, because it can get it an unmodifiable list view-- MATT SULLIVAN: So we're going to pass it. ANDREW BROGDON: --of articles. So we could just give it the articles like that. MATT SULLIVAN: Oh, when we instantiate the-- ANDREW BROGDON: Right. MATT SULLIVAN: Oh, that's clever. So we-- ANDREW BROGDON: So meet up a final-- MATT SULLIVAN: Kind of wouldn't want to do this in reality, because that list could be-- well, I mean, your search could be coming over HTTP, it could be coming from any sort of data source. We can pass this in. That's cool. ANDREW BROGDON: We need to-- you know, let's generate a constructor for me. Boom. I always forget to use those and they're right there. Command end. Visual Studio Code, I think, has some key command you can do to generate common stuff, too. MATT SULLIVAN: I'm sure it does. I should stop typing these things manually and work out what those bindings are. ANDREW BROGDON: I'm trying to force myself to do it like I've been needing a bunch of double equals and hash codes recently for some view model classes, and I've been-- MATT SULLIVAN: Shouldn't you just be using built value? ANDREW BROGDON: I should be using build value for my view models. The problem is I like to keep them in the class with the widget that's going to consume them. And that's tricky because of the way the build-- the built value stuff. As you've seen in some of our earlier episodes, the build value-- you know, you put your class in its own file, it generates a part file that sits next to it. MATT SULLIVAN: Yeah. ANDREW BROGDON: And that can be a little bit awkward if you want to have anything else in that file. Works great, but you have to structure your code a little bit specifically for that. OK. So we have this. So now we can go back up here where I now have an error and give it widgets.block.articles, which is a stream. MATT SULLIVAN: Oh, you're passing in the stream. ANDREW BROGDON: Is this a value stream that I can get a value out of? MATT SULLIVAN: Gives a stream of list of articles right now. OK. Because we're using stream. ANDREW BROGDON: OK. So I should be able to do that instead of future. How to do this correctly. Because you could-- MATT SULLIVAN: Because there will be nothing in this until such time the block resolves the stream. ANDREW BROGDON: Right. Which isn't that big of a deal. We can check and be like, oh, there's nothing in the stream yet so-- MATT SULLIVAN: Why don't you use a FutureBuilder? ANDREW BROGDON: Would we want to-- so say there's nothing in there yet and somebody hits the search button, do we want to delay and then pop up the search thing after the network call completes, or would we want to just say, hey, I don't have any articles yet so have fun with that. MATT SULLIVAN: Well, if you pass in the stream, then you don't necessarily have to wait because it will still resolve here, right? Because the stream will eventually start pumping data through at some point. Now, you could wait, or you could just-- because we're going to have to read a stream, when you have a stream builder on this side, it's only really going to start to resolve when you have data coming through the stream. ANDREW BROGDON: And so this is-- these are behavior subjects under the hood, which means they have a value to start with, right? MATT SULLIVAN: It means it remembers the last value that went in, unless you put this-- unless you seed it, it won't have a value at the beginning. But every time you create a new stream builder, it will immediately pull the last value from that stream. So I don't think we're seeding it because we have nothing to seed unless we seed an empty list. But if we pass in the stream, we can still do the whole stream plumbing. ANDREW BROGDON: Interesting. OK. So we can pass in this, and I go down here and say where I said that before, actually meant stream. Right. MATT SULLIVAN: And one of the ways that I typically solve this is I have an Inherited Widget which contains a stream, and then I can access it anywhere. We're just passing it through manually at the moment. That's totally fine for an app of this size. But now that we have the stream-- ANDREW BROGDON: We could return a stream builder here. Could we not? MATT SULLIVAN: We need to return a-- yes, we could. Because it will take a new widget. ANDREW BROGDON: And so we need to type our stream builder. We should be getting a stream of unmodifiable list view article like that. MATT SULLIVAN: Unmodifiable mouthful. ANDREW BROGDON: Yeah. And-- oh, actually, that's results. Let's do suggestions first. MATT SULLIVAN: Yes. ANDREW BROGDON: Because suggestions come first and so I'll return. I'm just inventing the new name-- new names for widgets right now. That's what I do. Alternative widget names. So what do we need for a stream builder. And we need a stream which we can give. That's just our articles. And we need a builder. And so this is one of the things I like. I don't know if the S code does this. You get the nice little hover. Because I can never remember what the signature is for builders and [INAUDIBLE].. MATT SULLIVAN: Excuse me, but the S code has hover, as well. ANDREW BROGDON: There you go. MATT SULLIVAN: Your insinuations. So we're going to start with the-- the IDE wars, here. ANDREW BROGDON: Yes. I do everything in vi from the command line. MATT SULLIVAN: There's a plugin for dot for vim. ANDREW BROGDON: Oh, yeah. MATT SULLIVAN: Next on The Boring Show. Flutter for-- ANDREW BROGDON: Another episode that involves me trying to learn to use vim. OK. So we're taking this and it's an async snapshot. MATT SULLIVAN: And you kind of want to type this one because it helps the-- ANDREW BROGDON: Snapshots. Still getting yelled at. Oh, because it's an unmodifiable. MATT SULLIVAN: Cool. ANDREW BROGDON: Here we go, everything's great. All right. MATT SULLIVAN: So the [INAUDIBLE] plumbing we're going to need now is if there's data or not. ANDREW BROGDON: That's right. So let's say if-- and I'm just going to do-- MATT SULLIVAN: You could do snapshot, that has-- ANDREW BROGDON: I'm going to say if it doesn't have data-- has data-- MATT SULLIVAN: I use has data for FutureBuilder. And I can't remember if I use stream builder. I usually use the connection state. ANDREW BROGDON: For right now, I'm just going to return a child that says, no data. Like that. Semicolon. And, otherwise, we can return something that means something. So we could do-- we're going to need a column of rows, I imagine. MATT SULLIVAN: List view. ANDREW BROGDON: Oh, list view. MATT SULLIVAN: Because we're going to have an unmodifiable list. The easiest way to do this, probably, at least to see if it's working, is to have a list view of the articles. ANDREW BROGDON: OK. Yeah. That's a list view, children. So we're going to map our articles to something. MATT SULLIVAN: We can map them just to the title for the moment. ANDREW BROGDON: Map to widget. So we're going to take an article and we're going to convert it to a text with a dot title. MATT SULLIVAN: Do you want me to text Will and find out what font he wants us to use for this? ANDREW BROGDON: I feel bad because he didn't have enough time to finish his work. And like he showed a bunch of really useful stuff about the API, and things like that. But like, you know, his personality, he wanted everything to be like proper and finished when he was done with it. And they just didn't have time. MATT SULLIVAN: I can't wait to see what he thinks of our search implementation. ANDREW BROGDON: OK. So let's save that. No data. MATT SULLIVAN: Yeah. That-- well, result-ish. ANDREW BROGDON: Yeah. That's interesting. OK. So let's-- MATT SULLIVAN: Oh, maybe because the-- maybe we'll need to re-- no, that should-- ANDREW BROGDON: Let's just start this up [INAUDIBLE].. There we go. So we had-- MATT SULLIVAN: So we do have data now, it's just-- ANDREW BROGDON: We do have data. We just have me forgetting to put to list on the end of my maps, as I always do. MATT SULLIVAN: Yeah, I do that, too. ANDREW BROGDON: There we go. So we've got some data. And then we didn't actually--oh, I am not in the search bar. So there we go. So we're not actually using a query, which we need to do. MATT SULLIVAN: So-- OK. Do you want to-- should we start the list, or should we get-- we get the [INAUDIBLE] working first. ANDREW BROGDON: Yeah. MATT SULLIVAN: It should be easy. Because all you want to do, right, is you would just want to search for a substring. ANDREW BROGDON: Going to do aware and just do-- yeah, a straight up. We get for-- MATT SULLIVAN: So what we do in the list view section, we can filter the list by using-- I'm presuming Dart has a substring? ANDREW BROGDON: Yes. MATT SULLIVAN: We'll work it out. ANDREW BROGDON: Yeah. There's a-- MATT SULLIVAN: Contains. ANDREW BROGDON: --include container. So I'm sure there's-- the Dart string library's probably been around for a decade at this point. So it's got to be in there somewhere. Articles. Where? And then I probably have to give this a slam dunk. MATT SULLIVAN: I can see the Dart team talking to us after is going, really, you don't know the string API. ANDREW BROGDON: After you talking [INAUDIBLE] material, we'll get a-- we'll get a target date for the Dart team. So dot title dot-- wait a second. MATT SULLIVAN: Stream class [INAUDIBLE] library. We have a contains. ANDREW BROGDON: Wait a second. Oh. This is not even remotely correct. I'm operating on the stream. Snapshot.data. Just like my IQ was not-- title. There we go. Contains, yes. Can we do it to lower here? MATT SULLIVAN: I think you-- ANDREW BROGDON: There we go. Contains. MATT SULLIVAN: Well, contains actually takes a pattern, so you could do some pattern on that-- ANDREW BROGDON: Oh, my, here-- MATT SULLIVAN: But I think-- ANDREW BROGDON: Pattern is. MATT SULLIVAN: --we can use a straight string for this. ANDREW BROGDON: Can I format that? There we go. That's a little better. MATT SULLIVAN: Contains query maybe. ANDREW BROGDON: I can't-- that would be-- all right. Hold on. Open source check. Let's drill down. Returns true. If the string contains a magic other. Other is a pattern. Pattern is an abstract class. MATT SULLIVAN: This will [INAUDIBLE] a regex or a string, or maybe both. But isn't a string like a-- just an exact match for a regex? Oh, it's been so long since I've done regular expressions. Welcome to the regular expression show where we will spend the next half an hour trying to work out how to do basic substring magic. ANDREW BROGDON: No kidding. MATT SULLIVAN: Have we tried to run this? ANDREW BROGDON: Let's just try it with this and see what happens. MATT SULLIVAN: You might want to-- I think, navigating back and forth might reset the-- reset your-- it'll-- cause it'll kill the stream builder. ANDREW BROGDON: That needs to be results anyway. Let's just try hard restart here. So I can do carbon. Yeah, you can, just give it a string. MATT SULLIVAN: So that works except for when there's nothing there. ANDREW BROGDON: Yeah. Thanks, dark courting. MATT SULLIVAN: We'll reach your APIs better the next time. ANDREW BROGDON: We promise. So that gives us some results. We still need to do something better than this ugliness. So let's do something nice, or we could make a little-- MATT SULLIVAN: We could make a list tile. ANDREW BROGDON: Let's make a little-- yeah, let's make a little stateless. MATT SULLIVAN: I always end up making less tiles. Because, apparently, you know-- ANDREW BROGDON: Here is one. You're right, we got a list view. We could make list tiles. That was a good point. So we're going to map to list tile like that. What do I put in here? MATT SULLIVAN: Title. ANDREW BROGDON: Title. Well, that's easy, title. Oh, no, messed it up. Need my a dot-- here we go. MATT SULLIVAN: What else do we have in the article class? ANDREW BROGDON: Oh, it needs to be a widget. Text. Easy peasy. We could put a leading icon on it. Like an article. MATT SULLIVAN: Book. Bookmark. ANDREW BROGDON: Book. Bookmark border. MATT SULLIVAN: You know what else you can do you? You can put the substring as the URL if you're feeling-- ANDREW BROGDON: Oh, subtitle. Here we go, yeah. Text, I'm guessing. a.url. Whoa. MATT SULLIVAN: Why is it not showing the title? ANDREW BROGDON: This is a-- I think it's because we've-- there's been some heavy modification of the-- I'm guessing this title is just an-- this URL is utterly enormous, and maybe we don't want to show it. So let me do this first. MATT SULLIVAN: Yeah, let's take out subtitles, see what happens. ANDREW BROGDON: So that gets us-- that's better. But those are still-- you want to give them-- well, if that's the body text, then I really just need to do this. MATT SULLIVAN: But that's odd because like title should-- it auto styles it for list title. ANDREW BROGDON: Open source. So let's see, we got a build method in here somewhere, right? Divide tiles. Oh, my goodness. List tile's doing a lot of stuff. Title text is title style. MATT SULLIVAN: Yeah, so that should be much bigger. I'm surprised how small that is. ANDREW BROGDON: Which is using-- oh, it depends on your list tile. Style. So if this is body two, that would look a lot like a body text font. MATT SULLIVAN: OK. So it's pulling from this style. ANDREW BROGDON: All right. So let's go back. MATT SULLIVAN: We could retheme it. ANDREW BROGDON: And let me take that off. Say isn't-- I know for a fact you should be able to jam this in here. Right. That should work. And be huge and not-- it's done incorrectly. OK. Interesting. MATT SULLIVAN: We could just give it a font size. Might be-- ANDREW BROGDON: Style. Good old copy width. Font size. 10.0. How does that work? 16.0. There we go. MATT SULLIVAN: OK. ANDREW BROGDON: Again, apologies to Will. I'm sure there's a better way to do this. Format on my code. Take out our subtitle here. MATT SULLIVAN: Because you could do-- with subtitle you can just say text one line and end with an ellipsis, that way then it doesn't-- it doesn't overflow everywhere. But it's good enough. ANDREW BROGDON: OK. So now part of the issue here is that these are-- these are suggestions. These aren't even the actual results, which is interesting. So what's the difference between suggestions and results? MATT SULLIVAN: Transition from showing results by build results to suggestions from build [INAUDIBLE].. ANDREW BROGDON: After the user submits a search-- so is this going to be the same thing almost? MATT SULLIVAN: Well, notice that as you type, it's showing the suggestions. What happens if you hit Return? Does it then show a different set of results? Because suggestions don't have to be a filter of the list, they could be anything. ANDREW BROGDON: That's true. MATT SULLIVAN: So if we-- ANDREW BROGDON: Yeah, because technically you're suggesting things that could go into the query. MATT SULLIVAN: So it doesn't have to be built off that. If we hit-- because, usually, when the keyboard pops up, there'll be a search key. ANDREW BROGDON: Suggestions should be based on the current query string. If the query string is empty, it's good practice to show suggested queries based on past queries, or the current context. Query. OK. So when list tile on tap is called, query should be updated with the corresponding suggestion. And the results page should be shown by calling show results. So what we're supposed to be doing-- MATT SULLIVAN: Oh, but that shows the results. That's different to build results. ANDREW BROGDON: So we should be putting a-- MATT SULLIVAN: How could we trigger build results? ANDREW BROGDON: On tap. Should be query equals-- this is here. We could do it like that. Why are you yelling at me? What did I just forget? MATT SULLIVAN: You're missing the brackets on tap. Open and close brackets. You forgot those. ANDREW BROGDON: We could do it like that. Let's save that up. That worked. Interesting that it just eliminated our preview. That's interesting. OK. MATT SULLIVAN: Well, that's going to re-- that's going to rewrite the query, which is then going to filter everything out. So the question is how do we get build results to trigger? If you type something in and hit Return? There you go. So that's building the results. So that's the equivalent of hitting the Search icon on the keyboard. ANDREW BROGDON: So let's take out-- MATT SULLIVAN: Because what you want to do-- ANDREW BROGDON: Let's take out the icon on this one. And do it like that. So these actually look like suggestions now. I'm a little weird-- weirded out by the fact that should leave us with one thing in here. If we just put this-- MATT SULLIVAN: But, no, because that's now running your-- that's now building your container, because you've-- there's no longer a suggestion. It should be showing the results. See what I mean? ANDREW BROGDON: All right. Let's build some results then. So we would do the same basic thing here. We'd still have a stream builder, I guess. So we do a live update of your search query for you. And-- MATT SULLIVAN: So I guess-- ANDREW BROGDON: --we're bloating the code. We can clean this up if we have time. And here we could put the icon back in. And you know what, I'm going to give these a color. Blue. Just so we can tell them apart. Do that up. We'll go back up here and say, OK, that's it. Now, I can put our icon back. So we'll be able to tell these apart. And then this will have it on tap that actually closes with the article. Because if you had a result, then you're done, you want to close the search down. Or we could do-- MATT SULLIVAN: Or we could navigate to the article directly. ANDREW BROGDON: Would we want to do that back on the original screen? Because we have to close the search at some point, right? MATT SULLIVAN: Well, we can do the URL launch, and then we can still call the navigate.offpop after it, potentially. I'm not sure how that would interact, because the URL launcher is no wait. We can play around with it, see-- ANDREW BROGDON: OK. Yeah. And, actually, we've been going for a little while now. Do you want to-- we got some questions we're going to answer, and give you a chance to do some coding-- MATT SULLIVAN: Well, let's-- ANDREW BROGDON: --and finish this up. You just want to see if we-- MATT SULLIVAN: Let's see-- let's see where we got to, because you've got like Blue code and icons and all sorts of other things. ANDREW BROGDON: You don't want to-- you don't want to take over a project in a really weird state in like a few minutes? That's weirding me out. So I can type in that. OK. That gets me a results. And that closes OK. MATT SULLIVAN: I think it's because your har-- you're overwriting the URL. It's getting very weirded out, as opposed to just saying search. Because if you tap in it, it's not supposed to take you to the results because you're selecting it. And that should, actually, launch the article, if you see what I mean. ANDREW BROGDON: OK. We can-- I mean, we could close doing-- how do I close here, as well? MATT SULLIVAN: Yeah, because the on tap there is going to say I'm choosing this result as opposed to show it me again in the search result. ANDREW BROGDON: I can certainly do that. MATT SULLIVAN: So you can choose one. It goes back. Or you can search and click it and it also goes back. Of course, we're going to-- yeah, OK. ANDREW BROGDON: All right. So let's-- why don't we do some questions. Yes. Questions. And just a reminder, if you're watching, you can post questions for us and, you know, we'll try to answer as many as we can on the show. You can post YouTube comments right on this video. You can, also, as you can see from our whiteboard, you can use the hashtag Boring Show, Twitter hashtag and tweet them at us. We check those out whenever we can. And I have two for today. So one of them comes from Connor Aldridge. This is about a week ago-- week or two ago. And, it says, "I'm really curious about how you could remove the top gray status bar with the white background, because that both looks better and is what Google does." This is in one of our other videos they were asking about the-- Connor was asking about the notification status bar at the top of one of the apps, which a lot of apps get rid of. They sort of hide it away. And so Flutter does have a mechanism for doing that. You can customize it and do some other things. Let me pull up-- I have done it. When I was teaching myself Flutter, I made a little reverse game. And it has a game UI so I didn't want to have the status bar, or the navigation bar, at the top or bottom. And I also wanted to make sure that people didn't flip the device. So it was just a simple example, and I didn't want to have to deal with having two different layouts for it. Because I was but a wee newb at the time. And so there is a way to interact with what they call system Chrome. There's a library for it in Flutter/services, and it offers things like setting your preferred orientation. So if you want to lock your screen in portrait, or landscape, if you want to definitely enable the navigation-- or the navigation or notification areas, or definitely disable them and hide them away until the user taps manually to bring them down, you can do that. And you just make simple calls into various methods. So the system Chrome class. Here we go. It's got a bunch of stuff in here. Preferred orientations, you just give it a list of the orientations you want. And enabled system UI overlays, you give it a list of the overlays you want, or an empty list to hide everything. MATT SULLIVAN: So then you just give it a scaffold. You don't give it an app bar and that gives you your full page for handling material-- ANDREW BROGDON: I can still-- I can still have the app bar, it's that very top layer where you have like your battery and your-- you know, your Snapchat-- MATT SULLIVAN: Oh, so that [INAUDIBLE] all of those as well? ANDREW BROGDON: --and those little icons. That hides those away and gives you that nice, clean full screen interface that a lot of apps really like. MATT SULLIVAN: You still need to take into account-- you still need your safe area for notch devices. ANDREW BROGDON: That's true. MATT SULLIVAN: OK. Safe area is great if you do go full screen for pixel 3s and the iPhone Xs of this world, that will make sure you don't have to manually pad for those areas. ANDREW BROGDON: It'll do a media query on your behalf, helps with rounded corners, notches, stuff like that, which is why we made it the very first ever widget of the week way back when. So that was one question. I thought it was really-- a really good thing to cover. Another one was from someone named Jim Morrison. MATT SULLIVAN: The Lizard King asks-- ANDREW BROGDON: Yes, I don't-- I don't know. Fun fact. He and I actually went to the same university. MATT SULLIVAN: This one or the other one? ANDREW BROGDON: The Lizard King, Jim Morrison. MATT SULLIVAN: OK. Right. Sorry about that. ANDREW BROGDON: Yeah. And, he said-- this is actually a concern. He says, "One thing that bothers me about Flutter is that it seems to allow coders to easily slip into writing massively indented code." And Flutter is a fairly unopinionated SDK. You can sort of write it the way you want to. And so this is actually a very good thing to be thinking about, especially if you're going to be a team lead or something like that where you really need to set policies for other coders to follow, maybe beginners who don't have as much experience. And so I wanted to real quick highlight yet-- yet again Brian Egan's wonderful architectural samples, where I think he does a very good job of this. I think the best way to combat this sort of thing is to lead by example. And so if you're a team lead and you can show your people exactly how to separate things, like business logic from UI logic, you can go a long way to dealing with that concern. And I think Brian Egan here, he has-- if you look at his project structure, he has a presentation folder with all of his presentation level-- presentation level widgets, which are just delightfully simple. They're very simple-minded widgets. They just take basic properties and convert those into onscreen presentation. And if you go into his containers folder, now, you start to see things that are using business logic to create those presentation level widgets. And so as I've-- and, again, I've pointed a zillion people to these examples. If you would like to see some very well architected Flutter code that shows how to deal with those sorts of concerns, I highly recommend these. You can find them in our samples index at Flutter/samples. We have a curated index of samples. And you can also just, you know, throw it into search and do Flutter architectural samples. You will-- you'll find these suckers. MATT SULLIVAN: And a rule of thumb is if your own widget implementations start to massively indent or grow by number of pages, decompose them into individual widgets. In the long run, it will help reusability but, more importantly, it will help readability. And the age old use async and await in futures versus dot then, and that will also help with when you start to play around with a lot of asynchronous code, ending up in that pyramid of-- ANDREW BROGDON: The right word drift as it is called. MATT SULLIVAN: Oh, back we go again. ANDREW BROGDON: Which has been mentioned in some of my own pull requests, to be completely honest. I think Jonah pointed it out once. Yeah. All right. You want to switch and we can finish this up? MATT SULLIVAN: All right. Let's quickly see if we can get some URLs logic. ANDREW BROGDON: Yeah, let's do that last little-- put a bow on it and call it a day. All right. I'll just log in and check your email here while I'm at it. MATT SULLIVAN: Which idea is this? OK. Right. OK. What have you left me? ANDREW BROGDON: I think we just need that last little piece of whether-- where we're going to watch the URL, and where we're going to launch it. MATT SULLIVAN: So this is working well so-- I mean, people, you know, there is a lot of overlap here between the suggestion and the actual result. But in many search cases, you're not doing direct text search, you're doing much more contextual based search. So-- whereas, we do have overlap here. Now, what we could do is we could-- let's take a look at-- now, I have to get used to your PC. Where is-- OK. Here we go. Show search. Back again. No, no. Yes. Here we go. So we have build suggestions. And we have the search delegate class. Now, what does it say about returning results? ANDREW BROGDON: So that's what close does, right? MATT SULLIVAN: So close returns a result. And if we look at the implementation, that's hopping the results. ANDREW BROGDON: That's using the navigator and it's popping with the result, which is then caught by show search, right? MATT SULLIVAN: Yes. So, basically, that means that show search is returning a future of type article, which means we go back to-- it's not [INAUDIBLE]. I was confused even by that. Now, why is that red? ANDREW BROGDON: Oh, it's in navigate repo so we can push this when we're done. MATT SULLIVAN: So what we need to do is we need to go back to-- no. Oh, main dot Dart. Hang on. Overall the same one. I would definitely break this into multiple [INAUDIBLE].. ANDREW BROGDON: It's still a very small app considering how much hacking we've done on it, which I find fascinating. MATT SULLIVAN: That's very true. On the next episode, Will will style our search page. Because as soon as he watches this-- so where is our search. Show search is here. So what we're going to do is-- how are we going to do this? So this is going to return to future. So we could do on pressed, we would have-- remember when I said don't use dot then? ANDREW BROGDON: Well, you can-- I mean, on press can be async. You can throw an-- you can throw an async on there if you'd prefer to do that. MATT SULLIVAN: So I could do that, right? And then I can do this, right? And then I can do final result is this, and this is going to be-- well, I could technically do file-- ANDREW BROGDON: Yeah, it's interesting because show search does not have a type on it. MATT SULLIVAN: But we have typed it from the delegate. ANDREW BROGDON: So does it inherits the delegate there. OK. Interesting. MATT SULLIVAN: So it's inheriting it from this. ANDREW BROGDON: So even if you didn't put article result. MATT SULLIVAN: Yeah, because-- I think we can-- OK. I think Dart's smart enough to work that out. And I'm not just trying to make friends again with the Dart team after our miserable attempt at looking up string. ANDREW BROGDON: Sometimes you just try whatever would make sense, and it probably works. MATT SULLIVAN: We could just do print. Where are we? Oh, it was going to be-- I was going to-- I was going to do snack bar, but we're in scaffold and, you know-- ANDREW BROGDON: Yeah. Well, you could just throw a builder in there. MATT SULLIVAN: Fine. I'll do it properly. Fine. I'll do it properly. ANDREW BROGDON: We're going to launch URL anyway. MATT SULLIVAN: So the reason why I can't do that-- I'll do what I thought I was going to do just so we can see why [INAUDIBLE] dot show snack bar. Snack bar. And if Emily Fortuna is here, we'd call this admiral snack bar because-- ANDREW BROGDON: Because she's funnier than us. MATT SULLIVAN: Yes. And it's funnier when she says it. Snack bar takes content. Spot the person who's written a shitload of snack bars. Why are you not-- ANDREW BROGDON: I think it's snack capital B bar. MATT SULLIVAN: And then we would do text and do results.title. Why not? Does that look right? Let's put some commas in. ANDREW BROGDON: So it's alt command L to format. MATT SULLIVAN: Alt. ANDREW BROGDON: Or option and command L to use. There you go. MATT SULLIVAN: Thank you. You learn something new every single day. So this is not going to work. And the reason this isn't going to work is because we're trying to get the context-- we're trying to get scaffold out of the context, but it hasn't been built yet. And this used to mess me up all the time, and I'd pull it out. And the easiest way to get around this, as Andrew pointed out, would be-- how do I wrap with widget? ANDREW BROGDON: Option enter. MATT SULLIVAN: This is what happens when you let me drive. You can put a builder in. And our builder is going to have a builder. And then we're going to put in a context. And then we're going to put in a double arrow. OK. So what does this look like? So if we go back and we do search and click on this. Now, I'm not surprised that work. It's always going to work first time. ANDREW BROGDON: So real-- real quick, just to make sure that we're being clear about what-- why we put this builder in here. MATT SULLIVAN: Yes. ANDREW BROGDON: So when you tell it scaffold of, and you give it a context, it goes, OK, I'm going to go from here up, and I'm going to look for a scaffold. MATT SULLIVAN: It's going to look up the widget hierarchy tree, but the problem here is when we called this, we haven't actually built scaffold yet, or it's not necessarily in context. So if I remove this option-- what is that, return? ANDREW BROGDON: Alt option enter, yeah. MATT SULLIVAN: Option enter. So if I remove widget, where should we move widget? ANDREW BROGDON: I don't know. MATT SULLIVAN: [INAUDIBLE]. If you were to remove this, this would actually throw a runtime error. ANDREW BROGDON: Because it wouldn't be able to find the scaffold. MATT SULLIVAN: Exactly. ANDREW BROGDON: Right. MATT SULLIVAN: So the thing is that if you use scaffold it of in the same build function that you're defining the scaffold, you will hit problems. And it's the same with whenever you use dot off. So the easiest way instead of having to break things up to multiple build functions is to wrap it in a builder, which gives you a separate build context to measure. I've explained that badly. So let's see if this also works. If I search-- ANDREW BROGDON: I think you're still-- I've done that a time or two, as well. MATT SULLIVAN: If I search for Neil Armstrong-- oh, dear, I've-- ANDREW BROGDON: Did we-- oh, you're broke. You're at breakpoint. MATT SULLIVAN: I broked. ANDREW BROGDON: Exception. OK. What is going on? MATT SULLIVAN: I don't know, let's just continue there. OK. So let's search for Neil. Neil's gone. Neil is there. Oh, because you're lower casing it. ANDREW BROGDON: And I didn't lower case the query. MATT SULLIVAN: Lower case the query. ANDREW BROGDON: Where's my-- where's my cone of shame? MATT SULLIVAN: Well, we'll fix that in a minute. So if we hit Return, we get the thing, we click the thing, we get the snack bar. ANDREW BROGDON: Right. MATT SULLIVAN: So let's take this to its foregone conclusion. That sounds very ominous. We leave that there for the time being. But do we have your launcher in here already? ANDREW BROGDON: Yes. Because that's what that icon is doing. And so we can probably-- MATT SULLIVAN: Wrapper function for that. URL. ANDREW BROGDON: There it is. Yeah, if await, can launch article. Launch article. So you could probably take that exact thing out. Yeah. MATT SULLIVAN: And we'll go back up. Probably wouldn't ordinarily break this into a separate function. If await can launch, and this is going to be result. [INAUDIBLE] article, result. Snack bar's kind of redundant at this point. But let's just see what happens. ANDREW BROGDON: Everybody likes a nice snack bar. MATT SULLIVAN: You can choose this. ANDREW BROGDON: You might have already built this. You've already built this section of it, so you might need to do a hot reload-- or a hot restart. I don't know. MATT SULLIVAN: OK. Where is my hot restart button here? Oh, wait, this seems to have-- OK. I'm going to restart the app. I have no idea what those mean. ANDREW BROGDON: Those are the things that teach me the key commands. MATT SULLIVAN: And I'm going to comma this out because redundant. And we did the [INAUDIBLE]. So there should be no reason why I can't launch this here. So let's see where we get to here. So we get here and we type carbon. And then we click. ANDREW BROGDON: And there it goes. MATT SULLIVAN: So it was a little janky 'cause we're also pushing back, and whatnot, I mean, there are several ways around that. We could-- so we go back and then we show-- what we could do is we could launch from here. So what we could do, for example, is we could-- and let's see if I could do this real quick. And I'm going to take this before you tell me this is a terrible idea. ANDREW BROGDON: No, I'm going to tell you we've been going for almost an hour. MATT SULLIVAN: OK. Let's see if we can quickly get this done. As people frantically waive at me-- waive at me. ANDREW BROGDON: I don't think URL launch is important to this. No, we're still in the same file. That should be fine. Result doesn't exist. There we go. MATT SULLIVAN: And then we go back and we choose another one. Oh, this is coming from results. So I'm going to go here. Isn't this riveting watching you work up. ANDREW BROGDON: There you go. MATT SULLIVAN: OK. Little bit of work there just in terms of what happens when. But we've gone from having-- ANDREW BROGDON: No search whatsoever to-- MATT SULLIVAN: To having kind of cool-- I think it's pretty neat. ANDREW BROGDON: Yeah. All right. MATT SULLIVAN: And you can type up your code now that I've got it out for-- ANDREW BROGDON: Before I push it up to you. MATT SULLIVAN: --over it. Yeah. ANDREW BROGDON: All right. So I guess that is today. Hopefully, you've enjoyed watching us knock out some search for this. It's a fairly simple API, you know, you just get-- one call to launch it and there are four calls to return the widgets that you need to present the UI for searching. So, yeah. Again, please send us some questions on the comments for this video, or you can tweet us with the hashtag Boring Show. We always check those out. And we try to respond to your questions both, you know, in the comments and here on the show. But, yeah, we'll see you next time. MATT SULLIVAN: Thank you very much.
Info
Channel: Google Developers
Views: 54,227
Rating: undefined out of 5
Keywords: Flutter search support, flutter search api, flutter apis, showsearch, searchdelegate, app search api, flutter search bar, add search flutter, search functionality app, add search to may app, flutter developers, boring show, the boring flutter development show, the boring flutter show, mobile app development tools, google mobile app development, mobile app development platform, mobile application development platforms, app developer, google developers, GDS: Yes;
Id: Wm3OiFBZ2xI
Channel Id: undefined
Length: 57min 0sec (3420 seconds)
Published: Wed Oct 31 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.