Let's live code in Flutter (DartConf 2018)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
MATT SULLIVAN: Hello, everyone. I am Matt Sullivan, a developer advocate on the Flutter team. EMILY FORTUNA: And I'm Emily Fortuna. I'm a software engineer on the Dart team. MATT SULLIVAN: And so what we're going to do for the next 30 odd minutes is we're going to live code a Flutter app, and yeah. We're-- hopefully this is going to go smoothly, but this is-- we're going to start from the very basics and go all the way through. So we're just going to see what happens. There will be no slides. This will just be code, except for this slide, of course. And we'll see where we get to. So what are we going to build? EMILY FORTUNA: Well, we are in LA and I am so looking forward to checking out the food scene around here. I mean, I just had some food here, but I need to plan ahead for dinner. And I'm very particular because when I get hungry, I get angry. I might even get hangry. Do you think we could write a Flutter app that could help us out with that? MATT SULLIVAN: So I think what we maybe want to write is a Flutter app which finds local restaurants, shows them to us, shows some ratings, that kind of thing. EMILY FORTUNA: Yeah, let's do it. MATT SULLIVAN: OK, so do you want to start-- EMILY FORTUNA: Yeah, I'll do that. MATT SULLIVAN: OK. So what we're going to do is we're literally going to start from scratch and we're going to create a new Flutter app, and we're going to call it Nom Nom. OK. We are going to be coding pretty quickly for the next half an hour. We're going to be breezing through a lot of stuff, and we're not necessarily going to stop and explain everything because what we really want to show you is kind of the flow of how we develop. How do we use hot reload? How do we use the tooling that we have? And so there will be plenty more talks on Flutter and various aspects of it. We'll be around afterwards and we'll have the code up on GitHub. Help. So if we breeze over things that you might miss, then bear with us. We'll get to the end. We'll answer any questions afterwards. So what Emily has done is she has created the out-of-the-box Flutter app, and what are we going to use as an ID? EMILY FORTUNA: We are using VS Code, and you know, it's no Vim, but I'll accept it. And yeah, you can see other IDs at other parts throughout the conference-- that we thought we'd show something different. MATT SULLIVAN: Yeah, so there will be talks on Android Studio and IntelliJ, and they will be using it. But we kind of wanted to use Visual Studio Code. It's my IDE of preference, so for the person out there who built the plugin, we really apologize for what we're about to show, in case, you know, where we go with this. So what we have is we have fired up the out-of-the-box app. Now, you may have noticed that that took maybe eight to 10 seconds to compile. That's the initial build because it's got to do all the Android-y stuff and package the APK. But you'll see, in terms of how we develop with that, that's not going to be the case going forward. So what we have-- Emily stripped out all the handy comments that we've put in, to help you with your initial app. And so, OK, we have a Flutter app. So why don't we change the name. And there we go. Hot reload. Emily hit save. About half a second later, that kicks off. So changing a name isn't that awesome. We'll be doing other stuff which will be pretty cool later on. So let's get rid of all the boilerplate that we have in there for this default app, and we're going to bring it back to Hello World. So we're basically going to strip it all out. We're going to create a new text widget because this being Flutter, all of the UI is composed through widgets. And again, we'll show you some of that as we go forward. And there we go. So we stripped it back. So we have the most, pretty much, basic app you can imagine. It's got a very small-- can everyone see the-- is this big enough? AUDIENCE: Yeah. MATT SULLIVAN: OK, cool. So we are back to Hello World. So what's the first thing we need to do to get this app going? EMILY FORTUNA: Well, let's create some dummy restaurant text that we can fill in to start with. MATT SULLIVAN: OK. Cool, so for Hello World, we're reusing the stateful widget that the out-of-the-box app gave us. You don't need a stateful widget for things like Hello World, but because we're going to build a list of restaurants that's going to update, we're going to need to be able to track state. So what we're doing now in our state is we've got a list of strings that's going to hold our restaurants or our places. And we're going to initialize that through the-- by overwriting in its state. And we're going to populate that with probably a bunch of strings, just so we can get the list up and running. And as you can see, as Emily is typing this, the Visual Studio plugin-- notice how it's recommending things, how when we hover over things, it gives us the constructor and whatnot. And it's how the excellent work that the tooling team has done to be able to enable this, so we can put this into multiple IDs. So great. We have got some state now, and we have a list of-- what's that going to be? 100 dummy restaurant names. So I guess we're going to swap that out of our texture. What are we going to use to show the list? EMILY FORTUNA: There's this list view widgets, and you can just pass in a list, and it will display all those children. So-- MATT SULLIVAN: Perfect. So we're going to use a list view. Now, if you have developed on other mobile platforms, sometimes, like, creating performant scrolling lists can be involved. The nice thing with Flutter and the Flutter widgets is that we've taken care of that for you. So Emily has created a new list view in place of the Hello World child, and notice that, again, we have to use widgets to compose the UI. So as opposed to just rendering the strings, we're creating a new text widget, and I'm not talking fast enough. You're typing faster than-- OK, that's fine. And we have a really uninteresting and kind of ugly list of strings. EMILY FORTUNA: I'll point out also, I had to do a full restart there, as opposed to the hot reload, and the reason for that is hot reload is great for existing objects that have already been built. But we added this places list, and so to create that, we needed to do a full restart. MATT SULLIVAN: So rule of thumb always is that when you're working with widgets and UI, hot reload is great. If you change your state, programmatically, or you change the code rendering your state, do a full restart. But how long did the full restart take? EMILY FORTUNA: Let's see, it only took just barely over half a second. MATT SULLIVAN: There we go. So hot reload and full restart-- it's all going to be subsecond, in terms of updating. So we have got a list of strings. We have our app, but we kind of need to get some data. EMILY FORTUNA: Yes. Matt, would you like to take the keyboard? So we're going to be using the Google Places API to get information about a specific location and return restaurant data. Now because, alas, poor Matt does not speak URL, we are going to be copying in a places file that has the URL we're going to be using to request that data. So I mentioned this place is API. There's a couple of ways you can call it. There is the HTP RESTful API. But there's also iOS and Android API, as well. But since we're going to code it all in Dart, we got this. All right, so Matt has pulled up this places file. It's a standalone file, so we can run it from the command line and you can see what data we're pulling down first, and then we'll hook it up to our Flutter app. So we've got a main, we've got a place class. It has a name, rating, address, and then we've got our little constructor and a nice two string for the results. All right, so down to get places, which is where the interesting stuff is, here is this URL that we did not want to try and remember. MATT SULLIVAN: Yeah, I can't believe you didn't think I could remember that. EMILY FORTUNA: Yeah, well. MATT SULLIVAN: Look at it. EMILY FORTUNA: Sorry. Maybe next time. So we've got a location for latitude and longitude. In this case, we're passing in some dummy coordinates for Venice Beach, which is where our current location is. And then, we're going to make a request to give me restaurants all within 500 meters of this specific geographic location. And then we're passing in this key, which tells Google Maps, hey, this is who's making the request. MATT SULLIVAN: Nobody gets to see my private key. EMILY FORTUNA: Yes. So to do this call, we're going to be using the HTTP library. You probably want to-- we need a package. MATT SULLIVAN: I need to add the dependency, right? EMILY FORTUNA: Yes. MATT SULLIVAN: OK. EMILY FORTUNA: So to do that, we're going to open up our pubspec.yaml, Specked and Matt's going to add this HTTP library. And you see this little carrot here that's saying I'm going to use anything 0.11.3 or above. And then on save, it pulled down the package right there. MATT SULLIVAN: Handy feature, again, of the IDs is that it's automatically pulling the packages, as soon as I edit the pubspec. So we should be good to go. EMILY FORTUNA: So back on places, we now have the package. Do we have the import? MATT SULLIVAN: Mm-hm. EMILY FORTUNA: We have the import. Cool All right. Scroll down again. And so, getting HTTP information is pretty easy with Dart. You just call HTTP.get pass URL, and then you pass in a callback that you want to be called when you get your results. In this case-- so it returns the future, and you call-- in this case, we are printing out the results. So Matt, you want to run this on the command line? MATT SULLIVAN: All right, let's get this running. EMILY FORTUNA: All right. Unreadable JSON. MATT SULLIVAN: We have some JSON. End of presentation. There we go. JSON. Done. Woo. [APPLAUSE] EMILY FORTUNA: So OK. So we've got some JSON. Now if this were an interview problem, your next step would be to parse all this into [INAUDIBLE] objects. But because this is not an interview problem, we are going to use the Dart streams API-- MATT SULLIVAN: Yes, we are. EMILY FORTUNA: --to parse this JSON in a nice way. So you see the code down here. We are creating our HTTP client, making the request, and then we're creating the stream API. So for all of you people that are very familiar with Dart streams, they're old hat. But in case you're not, the difference between streams and futures are they're both asynchronous, but a future is returning once, whereas a stream is returning multiple pieces of data. So in this case, yes, we're making that HTTP request and we're returning once, but then what we want to do is turn that stream into a stream with multiple pieces, where we are returning each individual restaurant that is in the results as an item in the stream. MATT SULLIVAN: So how are we going to break this down? EMILY FORTUNA: So we are going to call this transform to decode the-- because yeah. If you print it out right now, it will just be a bunch of bytes. MATT SULLIVAN: Let me quickly show that I've got some stuff done here. So we listen to the stream and then we close it on [INAUDIBLE] Actually, let me show you with just the bytes. EMILY FORTUNA: If you can't read URL bytes. MATT SULLIVAN: Here we go. That's even better. EMILY FORTUNA: Yeah. All right, so back to transforming it into interesting things. So let's go back to transforming it into a readable string with that UTF decoder, and we can transform it into a JSON object. MATT SULLIVAN: Yep. EMILY FORTUNA: And then we're going to call this expand method, and this is where we're taking that one JSON response and, like, parsing it out into individual restaurants from the results. MATT SULLIVAN: And the nice thing about this-- this is a real world example using the Google Places API. There's a lot of metadata in the JSON, so what you see here is we really want the results list, which is embedded in the JSON object. So we're digging in, we're making sure the typing is correct, to make sure that it knows the JSONBuddy is a map, and then we're expanding the individual pieces and the results to get out a whole bunch of not-- EMILY FORTUNA: JSON objects? MATT SULLIVAN: Yes. Thank you. EMILY FORTUNA: Yeah. And so now we have these JSON objects of restaurant results, and we want to make place objects. And so that's what this map method is about. We're constructing a new place from that JSON. Cool. So now, if you print it out, you should get-- we can make use of that nice two stream method. MATT SULLIVAN: So we have gone from a bunch of bytes through streams to a bunch of-- EMILY FORTUNA: All right MATT SULLIVAN: --places. Yay! EMILY FORTUNA: We can use an HTTP restful API! OK. So let's get to the exciting stuff. Let's put this back up to Flutter. MATT SULLIVAN: Let's do more HTTP. That's awesome. EMILY FORTUNA: OK. So we do this. We want to return the stream that we just created-- MATT SULLIVAN: Oh dear. EMILY FORTUNA: --to our Flutter app. MATT SULLIVAN: So I'm going to be returning what? A future? EMILY FORTUNA: Return to your future. MATT SULLIVAN: It's going to be a stream, which I can't spell. And it's going to be a stream of place. Cool EMILY FORTUNA: Yeah. And then yeah. Cool. So let's go back to main. MATT SULLIVAN: Well, we're actually going to write some Flutter again, are we? OK. Good, good. Do I get to code now and not just comment and uncomment things? EMILY FORTUNA: Do. MATT SULLIVAN: Pressure. OK. EMILY FORTUNA: All right, so back in our main app, we want to call this get places call. So in its state, let's make a function called, listen for places. And then, let's define that. And since that get places is going to return a future, this is async, yes. MATT SULLIVAN: Whoops. There you go. EMILY FORTUNA: And then we may want to import our places.dart. But then we're going to call it places. MATT SULLIVAN: Oh, we need to-- yeah. So we need to import our places. I got you. Places.dart. Am I talking while I code again? I do that. Yeah, sorry. OK, so listen for places-- async. I guess we're going to grab the stream, yeah? EMILY FORTUNA: Yeah, call it get places. And then we can pass in those Venice Beach coordinates to start with. MATT SULLIVAN: All right, let me get those coordinates, so we can just pass those in. OK. EMILY FORTUNA: All right. And you want to do a wait. MATT SULLIVAN: I do want to do a wait. Why do I want to do a wait again? EMILY FORTUNA: We're getting this future, and then we want to just get the stream from the future. And so it's a nice way of saying, hey, don't proceed on execution until the next step until I get that result. MATT SULLIVAN: But the result is going to be the stream, not the full list of things, right? EMILY FORTUNA: Right. MATT SULLIVAN: Yeah, OK. EMILY FORTUNA: So now, our stream-- we want to say, yes, we want to listen to the stream, and we want to say, hey, for each place object we get, we want to convert it to a Flutter widget. Or actually, we want to add it to our list, to start with. MATT SULLIVAN: We want to add it to out list, OK. So I'm going to add it to places, but that's going to be the wrong type, so-- EMILY FORTUNA: Yes. Change to place. List of place. MATT SULLIVAN: And let me fix this. OK. EMILY FORTUNA: In places.add, right? There you go. MATT SULLIVAN: There we go. OK, good. EMILY FORTUNA: Cool. Now we want to scroll down for where we're actually printing out the stuff, and-- MATT SULLIVAN: This is no longer going to be a string. This is going to be a place object, and let's print out the name. EMILY FORTUNA: Cool. MATT SULLIVAN: Uh oh. What happened? EMILY FORTUNA: We added a bunch of state. We need to do a full restart. Oh, and we also need to set state. We need to tell Flutter that-- MATT SULLIVAN: Oh, you're right. OK, so if I do a full restart-- EMILY FORTUNA: There's nothing! MATT SULLIVAN: Here's the thing. Like, programming with Flutter-- it's like you do something daft in your app, like I did, and it breaks and it gives you some information, and then you fix it and you do hot reload, and boom. There we go. We're back in. However, there's nothing in the list because, as you correctly pointed out, we don't actually tell Flutter that our state has changed. EMILY FORTUNA: Yeah, so because Flutter wants to be efficient about redrawing, it won't actually redraw until you call set state to say your state has changed. So now we say each time we get a new place, redraw. MATT SULLIVAN: So this should work, right? EMILY FORTUNA: Yes. MATT SULLIVAN: Yay, there we go. So now we have an ugly list, but with actual, real data. OK. [APPLAUSE] EMILY FORTUNA: OK. MATT SULLIVAN: So we could end it here, and the Flutter team would be very sad. And this is a talk about Flutter, so we should make this look nicer. EMILY FORTUNA: Let's make it look nice, yeah. MATT SULLIVAN: So do you want to make this look nicer? EMILY FORTUNA: Yeah. MATT SULLIVAN: OK. So what we can do here is we're showing a list of places. So why don't we create a new widget which will render these places correctly. And the thing here is that these places are stateless. We're not going to be dynamically changing them in real time. We're just going to build the list of places. It will be fine. So we can use a stateless widget, and what we can do is we can just, in the constructor, pass in a place object and we can use that, then, to build up the widget. So this is-- usually with the stateless widget, make sure if you're passing any data in, just make it final because it's not going to change, anyway, because stateless widgets are immutable. And so what we need to do in order to make this look good is to override the build widget. And as you can see, again, the IDE is, like, adding the methods that we need to override, et cetera. And it's making-- oh, we broke it again, did we? EMILY FORTUNA: Yeah, well, build is not-- MATT SULLIVAN: Oh, OK. So we're rendering a place widget and builders are printing null, and Flutter is sad. So why don't we just-- EMILY FORTUNA: Build returns null makes Flutter sad. So-- MATT SULLIVAN: What are we going to use to make this look better? EMILY FORTUNA: We could use a list tile, since we've got an item in the-- MATT SULLIVAN: So-- EMILY FORTUNA: --whole thing. MATT SULLIVAN: --Flutter has a great collection of built-in widgets, and we're just going to utilize those to go from ugly list to something that is hopefully more pleasant on the eye. So we have this thing called a list tile. It takes a title, so I guess we can make the title the name of the place. And of course, you can't just use the string, because things are composed of widgets. So we're going to wrap that in there. Hot reload. Boom. Now we have a nicely spaced ugly list of strings. So what else can list tile give us? EMILY FORTUNA: List tile-- we have our root. We can do subtitle. MATT SULLIVAN: OK, so let's-- EMILY FORTUNA: And we can add the address there. MATT SULLIVAN: Let's add the subtitle and let's stick our address in there. We're going to wrap that, again, in a text widget. And, oh-- so this is looking a little nicer. We've got our addresses. We're probably bored of seeing text widgets, as well. So we should probably use something else. So how do we get your reviews up there? Because you want to know what restaurants-- EMILY FORTUNA: I want to know what's good. MATT SULLIVAN: Oh, good or not good. EMILY FORTUNA: So we can pass this leading parameter. It'll show things before that text. We can pass in the circle avatar and pass the rating in there. MATT SULLIVAN: OK, so we're going to use a circle avatar. In this tile, we've got this leading thing, which you'll see where it prints. And in the circle avatar, I guess we're going to put the rating. EMILY FORTUNA: Mm-hm. MATT SULLIVAN: OK, and again, because circle avatar is a child, we're going to use text. And of course, our rating is double and because we want to be correct with our typing, we're going to make that two straight-- oh, look. So that's looking nicer, I think. [APPLAUSE] And so we've got 10 minutes left, so we can stop. Now, what are you doing? Are we still going? Oh, you're changing the-- OK. OK. We'll keep going. There we go. OK, so what'll we do next? EMILY FORTUNA: Well, I want to be able to easily look from these, based on the color of the backgrounds, what are the really good ones? MATT SULLIVAN: So we're going to update the color based on how good the rating is, and we could do if, then, if, then, switch this, that, the other. We're not going to do that because what we can use is we can use interpolation, because a lot of the classes and widgets in Flutter have interpolation baked into them, and what we can do with that is we can use the color class. And we're going to linearly interpolate from red to green, and we're going to interpolate from 0 to 1, so if our rating is 1 to 5, we're going to divide that by 5. And then, using that, hopefully one line of code and hopefully this works, we're going to pass in the rating. And-- EMILY FORTUNA: It didn't. It's-- so-- MATT SULLIVAN: OK, so all of these restaurants are pretty close. So you're not going to see-- you can see the-- OK. We're not being mean to this. They just don't have any ratings. So we've given it a minus 1. Please go there. I'm sure they're wonderful. EMILY FORTUNA: Please rate it. MATT SULLIVAN: But the point is that we have this nice-- in one line of code, we have this blend from red to green. We can slide it straight in, and this is how, like-- the joy of developing with Flutter is we're messing with these things. We're trying them out. We're trying new things, and now we have your app, which lets you work out where you would like to go or not go. Are you happy? EMILY FORTUNA: Well, once I visit one, I want to, like, check it off the list, you know? MATT SULLIVAN: You want to check it off the list? EMILY FORTUNA: Yeah. MATT SULLIVAN: OK. So with the 10 minutes we have remaining-- nine minutes we have remaining, we're going to make Tinder for restaurants. We're going to swipe right to like-- that's left. And the other way to dislike. And how are we going to do that? Well, there is a dismissible widget that's handy in the Flutter library. Notice how, again, we use the IDE to wrap the widget around the existing widgets. Again, it just makes your life much easier. Dismissible takes a key, and the reason dismissible takes a key is that the dismissibles need to track what's been dismissed and what's hidden. So in order to do that, it has a key associated with each one of them. And-- oh! [APPLAUSE] It does things like that. I need to talk faster, clearly. And so this is great. We have this dismissible. We have a key, but I don't know if swiping right or left is good or bad. So we need to fix it. EMILY FORTUNA: Yeah, we can-- let's see. So if we look at a dismissible-- hover. So you can set the background, secondary background, depending on which direction you swipe. You set a color. MATT SULLIVAN: OK. So let's set the background and secondary background. Again, we can use colors. And so we can put in a color. Now, we need to use widgets, so we're going to put in a container and we're going to color the container for that. You could put in, like, any widget. You could put in images. You could put in whatever you feel like. We're just going to simply do this with colors. So we're going to make a background green. We're going to make secondary background red, and boom. Dismissibles change state. We need to do a full restart. Oh, it costs us an extra 200 milliseconds. We're so sad. And now, swiping left, you get your green, and swiping right, you get your red. So we have Tinder for restaurants. We've got a few minutes left. We want to-- we didn't actually get much past this when we were planning this, so let's see where we get to with this one. So we have dismissed it, but we're not doing anything with the data where we're dismissing. EMILY FORTUNA: Yeah. MATT SULLIVAN: So what can we do with the dismissible? EMILY FORTUNA: I want to know-- I mean, color feedback is great, but it would be nice to know-- get a little more specific feedback of what these swiping things mean. MATT SULLIVAN: You want to have visual feedback on that. EMILY FORTUNA: Yeah. MATT SULLIVAN: OK. So the first thing we're going to need to do is we're going to need to detect the dismissed. And so we have this handy on dismissed. And on dismissed, as far as I remember, returns direction. And this-- we're going to be able to go, is it a left or a right direction? So we're going to be able to check if that direction is-- so we're going to check if the direction is equal to dismiss direction left or dismiss direction right. What have we got? End to start. And what's the other one? OK, perfect. So we have we like and we don't like, and we hope that they're in the right direction. So if we then do, again, full-- EMILY FORTUNA: Oops. MATT SULLIVAN: A full restart. Uh-oh. There we go, and we swipe in one direction. I like! Well, actually got it backwards. EMILY FORTUNA: At the very bottom. MATT SULLIVAN: But you know, that's fine. EMILY FORTUNA: OK, let's actually see it, though. MATT SULLIVAN: OK, so we've got a couple of minutes. Yeah, lets see where we can get to with this. So why don't we show this visually on the screen? And so handily, we're using-- this is wrapped in a scaffold, and the scaffold gives us access to a snack bar. So what we can do is we can pull up the scaffold object and we can show a snack bar. So, great. What we need now is we need a widget which is going to be snack bar widget, probably. EMILY FORTUNA: Oh, snack bar? MATT SULLIVAN: Because we're showing snack bar. EMILY FORTUNA: Yes, my bad. MATT SULLIVAN: Well, we'll add returns in in a minute. We'll make this look nice. It'll all be good. It'll all be good. So we go to snack bar, and a snack bar is going to take-- EMILY FORTUNA: Content. MATT SULLIVAN: Yep. And we're going to give that some text. And then we're going to-- EMILY FORTUNA: I think I parentheses messed up. MATT SULLIVAN: We got parentheses messed up. We can bounce these. One more. There we go. And so what happens now when we do a full restart is going to be we swipe left or right, and we're going to print. We swipe the other way, and-- EMILY FORTUNA: We have it mixed up, but-- MATT SULLIVAN: Well, we've gone off script enough that I think probably a good place to stop. Do you think? EMILY FORTUNA: OK, OK, OK. MATT SULLIVAN: Oh, we're going to do-- OK. There we go. EMILY FORTUNA: There we go. MATT SULLIVAN: There we go. [APPLAUSE] We're going to finish showing you just a couple of things while we have a couple of minutes. When you're building these, there's a very handy overlay for looking at how your widgets are rendered. We can just switch it on and off and toggle it from the menu. You can see here this is actually live overlaying on your device or in the emulator, showing you where your padding is and everything else. We haven't changed our padding much, but this is really handy when you're building your widgets you want to work out exactly what's going on there. EMILY FORTUNA: Yeah, if you have custom widgets-- since we used basically all out-of-the-box stuff, we didn't adjust padding or anything. But if you're doing custom widgets and need to debug, this is your friend. Oops. Not that. MATT SULLIVAN: And then the one other thing we'd like to show you is performance. We want to take a look at the performance overlay, and what this will give you, like, as we scroll through or we interact with things-- this will give you, basically, what your refresh rate is. You're hitting your 60 FPS or whatnot. At the moment, we're doing pretty well with that because we've been using all the stock standard widgets. But this is very handy. As you build out your app, you can bring this up. You can play with what you've built. You can see are you getting just the performance that you need. A couple of handy tips there. I think we're good. We have Tinder for restaurants. All of this code-- actually, we lied because there is one other slide. All of this code is up on GitHub, and you can check it out and it's evolving and we'll continue to add to this over time. So-- EMILY FORTUNA: Oh, you can also check that poll request where I tried to make a slider to see the distance, depending on how far you wanted to walk. But then I maxed out our API requests per day. MATT SULLIVAN: Yeah. Bear in mind when you use a slider and you have it directly wired to your HTP request-- EMILY FORTUNA: You might make a lot of requests if you're not carefully writing it. MATT SULLIVAN: Emily destroyed my quota in Google Cloud. Thank you very much. We had to wait 24 hours before we could start playing with it again. Thank you very much for your time. It's been a pleasure. [APPLAUSE]
Info
Channel: Google for Developers
Views: 106,390
Rating: undefined out of 5
Keywords: flutter live coding, flutter coding, coding with flutter, how to code with flutter, flutter example, google flutter, mobile app sdk, ui designers, mobile app developers, app developers, ios developers, android developers, web developers, ui developers, Dart conference, dartconf, dartconf 2018, dartlang, Dart language, Flutter, AngularDart, dart web, dart javascript, angular framework, dart 2018, angularjs
Id: iflV0D0d1zQ
Channel Id: undefined
Length: 28min 38sec (1718 seconds)
Published: Wed Jan 24 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.