Emily is a senior software engineer on the Dart programming language team, making Flutter efficient, fast, and easy to use. In her 20% time she works on fairness in machine learning. Emily is an Anita Borg Scholar, has a Masters in Computer Science from the University of Washington and a Bachelors in both Computer Science and Linguistics from Rice University. When not hacking on computers she can be found acting on the stage or screen.View the profile
Emily has been a software engineer at Google for close to three years. She is an expert on the Flutter framework, and is passionate about exploring the intersection between machine learning and user interface design. She received her bachelor's degree in computer science from Carleton College in Northfield, Minnesota.View the profile
About the talk
Come watch a single developer code a beautiful app in real-time from the ground-up that runs natively on iOS and Android, all from a single codebase. Along the way, learn how to marry Flutter's latest multi-platform reactive UI elements, accelerometer, and audio capabilities with powerful Firebase SDK functionality. See this app painted to life piece-by-piece in under 40 minutes thanks to Flutter's sub-second hot reload developer experience.
Hello and welcome to Total mobile that made fun with flutter and Firebase. I'm a militia. I'm Emily Fortuna. Very own mobile app using flutter live here on stage. We're going to tell you a little story about our friend Francine. Francine was the proud owner of a pet store and she realize the one thing that she needed for her business was to write a mobile app. That would allow people to see her inventory Reserve Force if they were interested and so then when they came into the store, they would be on hold and they could have dropped them. Now. I know
the Google IO is the worldwide Gathering of aquarium enthusiasts audience a today will be live coding a pet adoption app for fish for Francine on stage Celeste switch over to the devices. We have these nice cars with information about the fish. They're nice animations that you can slide between the information about the fish there different some of the fish are even animated. And if you decide that a fish is the right one for you. You can hit that catch button
and it is reserved. Then you can hop over every can see it said it has disappeared from the view of the other phone. So no one else can reserve that same fish have you view which Emily has you can see that she was reserved is available. If she decides that start is not actually the fish that's right for her. Then she can swipe up. It has been cleared from your reservation. And if you decide that you have regret from if you let loose the wrong fish you can shake. And your fish is back
reserved has great sound effects to go along with all of your actions. So let's hop back to the slides. So whether you are creating an app to create a home for unloved marine animals or just coating up that after you've been talking about for years, but we hope you'll find today is just how easy it is with letter to make your vision a reality. One of the great things about flutter is you can get a native look and feel for both IOS and Android all from a single codebase. So you don't have to learn multiple new technologies just to get an app to
conserve all of your users. And not only is it a native look and feel it is an actual flutter compiles down to native code. So you don't have to sacrifice quality to get a great-looking app. One of the reasons that I always look forward to developing and flutter is hot reload. So all I have to do is type my code into the ID it's saved and then it's almost instantaneously on my phone. The only downside is I no longer have time to make coffee because my clothes are ready ready. Flutter also has many powerful
components that you can integrate with beyond the scope of flutter itself in this talk. We're going to be showing you how to integrate Cloud firestore, which is an option for your server side component of your app. You can also integrates the accelerometer. That's how we're showing you shake to undo and we're also going to integrate those crucial sound effects for the flushing of that fish and all of this is done in the same code base so that you don't have to deal with the hairy details of those device platform-specific apis. So I'm going to jump on over
to the coast and we're going to give you a little tour of what we're going to be eating before we go ahead and dive into the coding portion. We went ahead and wrote some class decorations for you cuz watching us type class regulations of kind of boring, but we'll do a quick overview of what the final looks like the top. We have our main function there a tree that's where we're going to be building our top level widget or components that were drying and it is very creatively called my app my app isn't getting the information from cloud
firestore or AKA fish database and then that app as to screen my app has a fish page and a corresponding fish page States now, you'll notice that fish page is a stateful widget. Where is all the other widgets you see are stateless witches if you remember when we demo we had that undo functionality. And so that's some information that we need to store that have a long-running a persistent action to the fish. So if we decide that we Need to undo that we have that so for this reason we're storing that in fish page
so we can have that long-running persistent state for everything else. We have stateless widgets so that it can just draw the screen whatever information we provide it. This page has a fish options. That is that Center section that allows you to scroll through all of the available fish that you are able to adopt and then fish options is made up of many profile cards and that's the individual cards that you have for your fish. Now. There's probably a few more class decorations in here. Then you would want to have if you were coding this app for real, but for the
sake of Life coding or putting it all in one file, so that is easy for us to jump around and for you to see what's going on. We do have one more file though hop over to the utils class. There are two classes and it fish data is just a convenience. So when we're writing information to Cloud firestore, it's going to be in the form of a map. And so Thursday to take set map converted into another object and then we want we want to write it back to Cloud firestore. We convert it back to a map. Local audio tools is just a rapper around the audio tools function or plug-in which
allows us to write files from locally from our devices. So let's go back to main and Emily has are at reading up on this device has so much switch over to the device you and see what we've got. Okay, I think this is a pretty good app to start out with obviously. We have a long way to go here have on apps on my phone. Why is that that's a good question. So actually this is a good illustration of flutters accessibility features. So if you are vision-impaired or
if you are giving a presentation you want to make sure the people the back roads are able to see the text. You can set the text size default text size on your phone to be larger and flutter. Respond to this and then increase all the text size is the app. So we increase the text size without changing anything in our code itself. Okay, so I know that but there's not really much of a time reading yet. Why do we go ahead and get some content in there? I think the most important thing to start out with is that we have some Nautica shopping for a fish sounds good
so we can do that by setting the color of that Center section. So we're in fish page State. There's a build message. This is a method that gets called when that you would flutter wants to draw this widget to screen bill doesn't exist for every single widget that you have. So here we are constructing a scaffold that provides the outline for a children widgets and where they should be displayed on the screen scaffold has it at bar. That's that title bar the top give me the name of our app that we have the bottom navigation bar that allows us to toggle between the two
individual views and in the bottom. We have this dish options as that. Play body so it took set the color Emily's going to wrap this in a container and set the color of the container. Now, why are we dropping this in another widget rather than just studying the color of fish options directly. This is actually a common design pattern and flutter to favor composition over inheritance. And if you can imagine we could potentially have parameters in FishHawk tennis is at the color and the width and the padding, but you can maybe have a hundred parameters and it could get pretty
overwhelming having a composition in the way. We build are widgets keeps are apis much leaner and it allows us to build a combination of us in ways that we might say maybe originally had never visits. So Emily specified Indigo. She's ready. She's hit save hot reload is happening with switch over to the vices. They're staring at forever and I would say so we didn't have to rebuild our entire app to get that to show up. So now I like the color but I think it would be nice if we had them content on top of
that. Alright. Alright, so we can do that by adding that profile card. So is our fish options right now. Let's go to that field function. And right now we have a placeholder container or so, they get rid of that and then we're going to construct a profile card. Emily's also constructing a default fish date that because right now we're not connected to our fish database on cloud firestore. So this tainted just had some placeholder images placeholder name and information so that we can see what it looks like before we connect to Cloud firestore. Y'all know
if you're familiar with darts, which was what we are using two codes. You might be noticing. Hey, Emily is constructing this profile card, but she's not using new anywhere. What's with that? Well, this is a good example of how the dart and flutter teams have collaborated flutter was saying hey, we have a lot of flutter users that are noticing that new is cluttering up there, cuz they're constructing all these widgets. What do we do? So the dark team made new optional and his part of two-point Dart 2.0. So now you can just write a profile card. Got it all written up.
We're going to hit and it's going to hot reload switch over devices. All right, we got a pretty empty card on here. I think what I want most in my viewing of a fish is to see the big picture of the fish. Okay? Okay. So let us modify the profile card. Tell me swap back over to the code inside program card. Look at their profile cards build function. That's pretty simple. We're just construct to call and get card contents and wrapping it in a card at the material widget get card contents does three things it's calling show profile picture, which is clearly
is falling down on the job. It is calling show data and then lastly show button to let's go in the show profile picture and make it actually display a picture. Take a take out that container and said and was calling fade an image. So usually we're going to be getting an image from cloud firestore. So that's a call to server that's potentially asynchronous data. So when we build we might not have that data at the moment of building. So for that reason now, you could just pass it an image, but once it has that image data, it might pop in that could be visually charge a jarring. So
instead Emily's making a faded image that once we have the image it will fade into view very nicely and then last night were specifying the fit so images have a width and height and insane box fit. Covers the span to fill all the evolved a little size, even if it means cutting off some part of the image, so he's going to hit save which hot reloads Andrew switch over to the devices. It already faded in didn't get to that so fast. All right, we've got our big picture of a fish, but I need to know more about that fish before I decide to adopt it. I
want to know the fish's name personality. Yes, that is very important for human fish bonding. So let's go back to the code and was going to modify show data and we have declared three text widgets. The first one is the name widget second one is the music widget fish is preferred music and then lastly preferred pH and to display those we're going to wrap those three in a column widget, which is going to stop them from top to bottom. Someone's going to hit save going to hot reload go over the devices. Do we see it? There it is. All right, so I can understand
but the information to little cluttered right now and I feel like his name is probably the most important piece of it. So, how can I set that apart so we can do that by setting the textile? So instead how about we make it bold and we could set we can double the font size that would help it stand out a little bit more. That way people can look up Frank. My name is let's look at the devices again. That's much better. I think we're getting there but I still think the Frank should be so back at the
code. How about we wrap that text message it in some padding. Now, there's a really handy feature with Visual Studio code, which is what we are currently using. This also works in Android Studio in IntelliJ. You can just wrap a widget inside of another widget. So it takes care of all the invitation for you. So he's going to wrap it up and some padding. Is that we're wrapping it in 8 pixels app a day, which is good enough for us. So we're just going to hit save hot reloading and look at our devices much better is in a pretty good place, but I'm a little tired
of looking at Frank. What if we have some real date in there? I like phrase. It's okay. Okay. So let's connect to Cloud firestore at the top of that my apps right now. We are passing an empty list cuz we're not getting any data from cloud firestore. So instead we're going to be making a call to Cloud firestore. So there are two different ways that you could deal with a secure to stay that because we're making a call to database or Cloud firestore to get our information the first way to deal with a serger to say that it's Futures
are promises depending on where you're coming from. And this is if you want one bit of data a sacredness Lee streams are your other option now streams are if you need multiple pieces of data, in this case, we want a snapshot of cloud of all the information on cloud firestore and then when something changes on that database we want to get a new snapshot of all the fish that are still there. So is this case stream is the correct option and then there's this convenience stream Builder, which allows us to build widgets from the Stream So Emily has specified the source of the
stream. This is forming Cloud firestore. We are getting a collection of fish profiles and we are calling the Builder. To build which it's based on that fish information. You might notice on the line 32 we had this interesting question marks in tax what's going on there? So what we're saying is still call. Documents and return that he was her sign that empty list to the documents variable otherwise get the documents from cloud firestore. And then we're taking that map and converting it to a fish day two objects. We
have a list of Fish dating passing it end of this page. Now, you might be wondering how we accessing the Spire store variable will get scroll up to the Imports. You see we had his package Imports. Particularly Cloud firestore. Where does that come from all over to pugs Beck? This is just a yam will file that allows us to specify all of our dependencies for Dart and our package manager. Is that able to calculate? All the versioning things suppose. I'm down from online sets of all the past correctly and then you're good to go. You just import them so back to her main
file. We have what we need to do. Cuz if you recall Emily constructed that fish data object that was default. I had no information now he want to take some of that stream that we just got from cloud firestore and display it. So here's you think if we had data just call the first one cuz we're only displaying one card right now. So now at least save it's hot reloaded switch over to the vices. We got some good. Okay, I'm looking it slow and I'm feeling pretty good. I think I might want to adopt her. I'm not really sure how I can do that from
this view. Yeah catch does not seem to be implemented. So I think it's time to implement that show button right now show button are on pressed parameter is not doing anything on pressed. We're going to pass in a function that is going to be called when he is our president. And in this case, we want the button to function as a toggle button between reserved and unreserved. I sort of me passing these if it's already reserved and reserve it otherwise preserve it is call backs haven't been implemented yet cuz we're not raining Cloud by your Source.
What's in pimentos? Those are this Reserve fish and remove dish. So we're up in the fish page State class right now. It would you recall is a stateful widget. So in this case we're going to be calling set state that tells the widget. Hey, there's something that might have changed in how I displayed so flutter, you might want to read raw me and then Emily setting the desert by field to this user ID. That's a unique ID when we sign into fire base and its unique / device and then remove fish is just the same except we set the reserve by field to know. So we have to implement
our same as if that's going to be actually writing to Cloud firestore that's inside fish data. And it's pretty easy. We're going to take our documents reference to that individual fish. And we're going to say that data and then we need map of ir object are but should be implemented. Let's hop over to the devices. Heart ruler to be in action, but got a button go Reserve at Emily. Okay, it's time. It was like I was their fault in the one device, but she's still available to be
reserved on the other. So I'm not really sure if I'm going to come into the store and everyone's going to think that they preserve flow we could get in a fight. Everybody wants flow. I will hop onto the computer and you can talk into the rest. All right. We have one fish showing we can reserve it on one phone, but it's not really showing a different fish on the other phone. So what we really want to do is pass in the list of fish. They are user can reserve are you there already has reserved to that particular user rather passing in all of our fish blindly.
We want to filter that list. So to do that we're going to use the. We're operator. Now. This is an example of functional operators in Dart operator, or if you were paying close attention when I was implementing the cloud firestore piece of this you would you would have seen the. Math operator. Both of these are examples of functional operators. And in this case, we are in a rating over every item in the all fish list and only returning a list of fish that meet the qualifications that the user has either reserves a fish or the fish is not reserved by anyone now, if we're in
that Reserve view, which is our shopping cart view, then we only want to display The fish that are reserved by the current user. So now when we hot reload and switch over to the devices, we should be able to see a new fish displayed Emily. I broke it. So it's not looking good. We have the red screen of Doom but it seems that we've encountered an error. So let's try to debug this here when you hit in there and flutter is going to show up on your devices in this red screen with a very helpful error message this error message is going to be a little bit more concise.
Then the more verbose version that you would see in your debug console. But let's see if we can get from here. It looks like from the phones. It said something like type where iterable is not a subtype of type list. So probably what was happening was that when we converted using the where operator it was converting to an iterable rather than a list because it was doing that a little bit lazily and not converting to a list until it had to we want to explicitly convert to a list. So let's go ahead and do that. I accidentally closed out of the
all right. So this is an example of why hot reload is so handy we appear to have accidentally stopped the app and it's going to take a long time to restart it with hot reload. You don't have to wait all of that time. So I believe if we switch back to the code. We're still going to need to implement that. List or. To lets out. Okay. Alright, how are the phone's doing we're waiting for iPhone. It takes so long can relate to this problem. This is why Emily is drinking so much
less coffee and tea after switching to flutter and using hot reload. All right. Why don't we switch to slide 19, which is our backup. Nevermind. Nevermind. We're going to go over and see if it's working so fast really saved us there. All right. Now I know that you didn't quite get to see this because we had a little bit of a technical difficulties but hot reload can actually hot reload past errors. So if the device isn't connected and we've been able to hot reload it would have shown up just like this instead of us having to quit out of the app after we'd had an error which can be really
handy in this case we're seeing is that when we reserve a fish now, the fish has disappeared from the other phone it appears. We're back to Frank. Okay, I think probably Firebase just had a little bit of time to load those fish. Now when we reserved flow flow is no longer available on the other phone great. Perfect. Alright, I don't know something doesn't seem quite right. I'm not really digging Marlon Brando. I would like to have some other options. That's true. We're only one fish right now. But as we all know
there are plenty of fish in the sea, and we would like to give you the option to adopt all of them. So why don't we go ahead and switch back to the code and we're going to try and Implement a cover flow widget widget that we are getting with another plug-in just like we got the fire store plug-in and that's the simple coverflow plugin takes into argument steaks in an item Builder and an item count item Builder is going to take in just basically the same code that we had before. Going to change that index in fish to make sure that when were just playing multiple
cards. We're not since playing flow every single time. Then we're passing in the length of the fish list to item count so that we're not going to scroll infinitely through coverflow now we should be able to hot reload and switch over to the phones. This is so much better. Look at all these fish. I could adopt I can adopt Gayle the whale except I don't think I had space for Gayle the whale can I ride on a little overboard there? Why don't we try and see how we can remove a fish from that reserved view that seems like a pretty handy use case for our users.
Go back to the code. We're going to implement two more arguments on that cover flow. We're going to add a dismissable items argument and that's going to tell coverflow whether it should be able to dismiss cards by dragging up or down and having those disappear from the list were also adding in a call back. Does miscible call back and that's going to be triggered whenever we do dismiss a card from the list and that's what's going to be using the same on remove call back that we implemented before. So let's go back to the devices hot reload and see that in action.
And I think I get scale is available for anyone else to the Reserve. I dont have space for Gail two-wheeled, but I think my parents have space for you, LOL. I do want to adopt her but I want to dismiss the fish and then instantly regretted. We want to give you the option to get that fish back in. So this is where we're going to integrate the accelerometer. So for this we're going to implement a very simple undo functionality. We need first of all our fish data to store at the fish that has last been undone or the fish that has last been removed from the list so that we can undo that later
on. They're going to talk about variable and then go ahead and set it whenever we remove a fish now. This is a pretty simple version of undue. We're only going to be able to remove one fish at a time that you can imagine some more complex version. We're moving multiple fish broad purposes. This is going to work just fine. So now we're going to need to actually trigger and undo with the accelerometer. Here were implementing and in its State method on fish page State Allstate for widgets actually have this and it's State method, but a lot of the time it's implicit and can just default to
the default implementation. It's going to be called whenever we start off that stayed in our case. We want to introduce our own logic. So we're going to explicitly write it out here. We're going to initialize a listener on to the accelerometer events stream. That stream is something that we're getting from the sensors plug in the background moved in some way in our case. We want to trigger a shake whenever our whenever the phone has accelerated in the x-axis by at least two
meters per second. And we also want to trigger a time do if we recognize the undo data is now and we're in that reserved View. So I believe yes, we have to impose are less than or equal to go ahead and you think I'm about to say hot reload, but I'm actually not there's another function here that we can use called hot restart hot reload is actually going to be stateful and bring you back to your current state. And yeah hot Resort is a little bit different because we have these in its state calls and maybe some calls in our main function before we built the
widgets. Those aren't going to get rerun when we do a staple hot reload. We want to fully restart the app to display our new changes but a hot restart is better than a full restart and that it's a lot faster actually almost as fast as a hot reload sweetheart restarted and we can jump on over to the phones. the reserving Gayo remove and get that perfect, and she's disappeared from the other phone. You know what really but the I'd be attending on the cake though. What's that? Because it sound
effects. Okay. So we want to incorporate sound effects using our local audio tools class, which is calling the audio tools plug-in. So here we are going to in the top of our main function. We're going to load a couple audio files are background audio and are removed audio. We're also going to initialize and audio loop on that background audio so that when we start out the background audio, it keeps playing until we may be interrupted with a different audio file. So this
would be a good time to pause and talk a little bit about asynchronous functions in dark. You'll notice that the main function is marked with the async key word. That means that it's a synchronous and is going to return the future or a promise of a value that's going to come a little bit later on. It's also calling to more asynchronous function. We have this Firebase off sign in anonymously call as well. As our audio Tools load file call different ways in the first case were using the away to key word. And what that thing is that we're feeling with an asynchronous function,
but we really don't want the rest of our main function to continue until this one has completed until the future has completed. So we're going to call a weight and that's going to pause execution on everything after that await call in our main function. For audio tools were using the. Then operator and that's going to cause execution of everything inside of that body of the operator, but it's not going to cause an execution on anything else still in our case. We want to wait for the file to be loaded before we can play it but we don't care if the rest of the Outfield a little bit before we
loaded our file. So we have one more place to incorporate audio, which is it whenever we were moving fish. Of course, we want to have a nice sound effect there as well. So we're just going to call play audio and then we should be ready to switch back to the apps to the devices so we can do another hot restart this time and then switch over. And we should be able to hear some Ocean Breeze sound in the background. As well as that crucial flushing noise when we dismiss a fish. That looks good.
I think our ass is pretty good. So why don't we go ahead and deliver this to Francine. Let's go back over to the slide. And this app is a huge success with Francine. She's so excited. She delivers it to her customers and it drives business by over 300% because of flutter, but how did we get here? Well using sweater. We were able to achieve a native customizable look and feel for both IOS and Android from a single code base But Not only was it a native look and feel we also did really compile down to native code under the hood. So we
didn't have to make any sacrifices in quality or customizability. We also integrated with Cloud firestore which gave us all of that fish data that updated in real time. And finally, we integrated our device level controls the accelerometer and sound to get that app really fully featured and all of this all of that functionality hard to believe but it was done in 310 lines of code. That's everything. We wrote in advance of the talk and everything we showed you today. So that's pretty low.
Water is currently in beta. What does that mean? Well, it means we support right to left in case you're ready to go fish adoption app around the Dead Sea. It means we support internationalisation also related for that. Let's see if it means that we support accessibility as you saw in our current ask flutter has apps in all sorts of Industries. We have financed Health music travel here are some of the brands and companies that are writing flutter apps. I want to highlight three of them for you. The first one is Hamilton if you haven't heard of Hamilton, I'm sorry. You're
probably not you probably don't live in the US. This is the music by Alexander Hamilton and their official app is written using footer. It has over a million downloads and over half a million monthly active users on the left. You see AdWords, which is the multi-billion-dollar products by Google. Helps keep the lights on and Google and their new app is also written in buttered is going to be released soon on the right. We have Ali Baba, which is the top 10 internet company and their new mobile app is written flutter and they're in
the process of releasing it soothes users now. If you want to learn more about flutter, we have so many great resources for you first check out flutter. IO that's where you have information about how to download it set it up on your computer. There's documentation. We have you done a 30-footer course you want to learn about it right now. You should run over to the Cove Labs. We have a whopping 9 coal as about flutter and dart and at various points today and tomorrow, you might see someone looks kind of like this and someone that kind of looks like this helping out. Also, we have a
Sandbox. There's a flutter Firebase and Cloud sandbox. We have a great selection of goodies there. There's this hot reload game which is pretty fun and wavy plated. I have actually played the hot reload game. It's great. It's also a great example of how you can get really good-looking 2D animations working and flutter. And there is one more talk tomorrow. That is good design patterns for your Twitter apps so seems like I have so many widgets. How do I manage them and how they talk to each other if you go to this app is talk tomorrow, and there was
one more talk that happened earlier today and if your time in order to check it out and pretty soon. Here is the code that we wrote today. This link will also be out in two slides. We love to have your feedback go to the web page. And then thank you so much great to the sheriff letter with you. We will take questions in the flutter sandbox and adopt a lobster.
Buy this talk
Access to all the recordings of the event
Buy this video
With ConferenceCast.tv, you get access to our library of the world's best conference talks.