[MUSIC PLAYING] CHRIS SELLS: Before
we get started, I'd like to tell
you my name is Chris and I am the product manager
for the Flutter developer experience. And with me is Matt, who is
the lead for Flutter developer relations team. And it's our job today
to tell you about Flutter from a developer point of view. Now, before we get into that,
let me ask how many of you are developers in the room? Excellent. I don't see any managers. That means we can
make fun of them. All right, so what is Flutter? Let's start there. Flutter is a new UI
toolkit from Google. And its job is to help
developers, you folks, build Quick apps of high
quality and high performance, and to do it across
multiple platforms and target them natively. That's the job of Flutter. And so our job is to
tell you about that. But before we tell
you about that, Matt is going to show you
how it actually works. Matt? MATT SULLIVAN: Most
of you are developers, so you'll be able to spot
the mistakes that I make. So we're at MWC. I want to spend 15, 20 minutes
just showing you the developer experience of Flutter. This is not to teach you
how to build Flutter apps. This is just to give
you a flavor for what it's like to build an app. So I'm going to go through
stuff pretty quickly. And anyone who wants to come
up and ask specific questions afterwards, or
between the breaks or whatever, please
feel free to. I'm more than happy
to ask questions. So the first thing that
was on my mind was, what am I going to
start to code on stage? And I figured since this
is Mobile World Congress, it would be nice
to build something that made phone calls, because
that kind of makes sense. So I'm going to see if I
can, in the next 19 and 1/2 minutes or less, put
together a phone dialer. Now, I am running-- I usually do this with an
Android phone hooked up to my Mac. Today I'm going
to use an iPhone. And this is a real phone. This is QuickTime
doing an actual cast. So everything you see here is
happening on a real device. And everything that I do today
I've tested and works equally well on an Android handset. So I thought I'd
shake things up today. So first off, how many
of you have actually written some Flutter before? OK, a few. So some of this will
be old hat to you, but hopefully there'll be
some interesting things here. Everybody has been
talking about hot reload and how it makes
their lives easier. So I have the world's
simplest app on here, which is basically
some center text which says, effectively, hello world. And if you get one
thing from today is that everything about UI
and positioning in Flutter is about building widgets. So I'm going to be building and
playing with a lot of widgets. So when I talk about widgets,
they're just the components that I'm going to do. So I have hello NBC. Let's change that and
say hello from Flutter. And there we go. Martin promised you 200
millisecond hot reload time. I'm afraid my laptop
only managed 751. But I got a lot of
stuff running in there. So hopefully that's
still sub-second, so that's pretty good. So there you go. Hot reload. I made a change. Not super impressive, because
I just changed the text. I can go in here and I
have done a little bit of theming on here. So as you can see, my colors
for my text are green. So maybe I can make
that dark blue. And there we go. That's faded dark blue. The text is a little big
for what I want to do. So let me drop that
down some size. And there we go. OK, so I'm already starting
to play around with it. And this is all well and good,
but this is, like, hello world, and we're 2 and 1/2
minutes into the demo. Let's actually do
something more interesting. So what I'm going
to do, I'm going to create my first widget. So I'm going to go and I'm going
to create a stateless widget. And I'm going to
call it my dialer, because I'm going to
be building a dialer. And what I'm going
to do in here is I'm going to start with
what does every dialer have? It has some buttons. So what I'm going to do is I'm
going to put in a digit button that I created. And this takes a character. So I can give it one. This isn't going to do
anything because I'm not using my widget yet. So let's take out this text. And let's use my dialer instead. So there we go. Wow, magnificent. He's made a button. That's really exciting. It actually works. There's the button
being clicked. But I don't need one button. I need several buttons. So how do you do
that in Flutter? Bunch of different
ways you can do it. Let's add a second button
and see how we get on. So I'm going to go
here and I'm going to use some of the tooling
that we've built into-- I'm using Visual Studio Code,
Android Studio, and IntelliJ. We have some really awesome
tooling for that, as well. I'm just going to make use
of this liberally throughout. So I'm going to create a column. I'm going to take
my digi button, and I'm going to replicate it. And then I'm going
to put in a two. And now I have two buttons. Great. And they're way at
the top of the screen, and that's kind of lame. So I'm going to tell my column
to lay out in the center. There we go. OK, so now I have two
clickable buttons. Maybe I don't want
them vertically. Maybe I want them horizontally. So maybe I can
change this to a row. And there we go. So you're seeing a
couple of uses here. I'm using widgets to create
actual elements of UI. And I'm also using widgets
to lay everything out. I'm doing everything
through code. There's no underlying layout
language being used here. And it allows me to iterate
really, really quickly. So this is great, but
what I really need is I need something
like 16, 17 buttons, and I need to do
them really quickly because you don't want to
see me code buttons all day. So I'm going to create
the stateless widget and call it my numpad. And what I'm going to do is
I'm going to use a table. And the table is going to let
me lay things out table-style. Now, I can hover over
and see what it is. One of the nice things
about Flutter, everything's written in Dart,
so I can actually go into the documentation
and I can read the documentation in my IDE. I can actually see
the source code for implementing
a table, which has got a lot of
complicated stuff in it. But the nice thing
is is I can always dive in and see how
things work under the hood and I can use them. So I've got a table. A table here takes
children, which are a bunch of table rows. So let's give this
some children. And that's going
to be another list. And these take a-- these take a table row. Whoops. Too much coffee. I should have not had my
fourth cup 10 minutes ago. Great, OK. So-- twitch, twitch-- table
row takes more children, which are just widgets. So let's go in here and let's
give this some children. And in here, I am
going to create an-- oops. I am going to create a map. And so what I'm doing
here is I'm just going to give this a few digits. Let's say 1, 2, 3. And all this is
doing is a little bit of fancy programming
to map those characters to some digit buttons. This is great. Nothing's happening
in the screen. Everyone's bored at this point. So let's just get rid of
these and we'll keep our-- let's change this
back to column. And I'm going to get rid of
these that are on screen. I'm going to put in my num pad. OK, right. OK, so now we're
getting somewhere. We have a row and we have these. So let's replicate
this a couple of times. 2, 3. And then we will watch with
anticipation as I cannot count at all. There we go. 7, 8, 9. This is so exciting. I should have done
this prepped earlier. And hash and we're done. Yes. There we go. OK, so we have a num pad. It's not that exciting, I know. But it's getting places. It's a little spread out
because this is an iPhone X and it's super stretchy. So I will unstretchify
that by wrapping this in a little bit of padding. Let's give that 25, say. And that's going to
shrink it down a bit. Cool, OK. So that's not bad. Seven minutes in and we
actually have some buttons. What are we going to do next? Let's show what those
buttons are actually typing. So I'm going to
put a new widget in and I created a readout widget. And I'm just going
to drop that in. Now, there's a couple
of things to note here. One is I've used a
pre-built widget. And secondly, there
are the numbers that I've been typing
in since we began. And this is the example,
again, of stateful hot reload. I was hitting those buttons. The state was being recorded
even though it's constantly reloading the UI
that is still there. And just to prove it, there we
go, even the Delete key works. So that's cool. So now we have a
readout, which is nice. We kind of need a button
to actually dial something. So there's a simple
dial button here. OK. And now we have the
basics of a dialer. That's kind of
cool, but you know, I kind of did some cheating
by I pre-prepared this readout and these dial buttons. So let's take a quick look
under the hood just to show you that there's no real magic here. So here's a few widgets
I created earlier. And here's my
number readout one. And it's got a little
bit of stuff in there in terms of setting margins,
in terms of playing around with nice, curvy borders. So let's play around
with a couple of these just to show that it's
fairly easy to modify. The first is we have
this nice delete button. I can go into my delete button
and you can see there it's an icon for a backspace. I could change that
up a little bit and maybe change it to
something different. OK, that's nice. I can play around here. You can see my borders
are quite roundy. I can make my borders
even more roundy. I can make my
borders less roundy. That's nice. Maybe I don't like this,
you know, two or three year old style of wrapping
everything in a border. Maybe I just want to have
it nicely underlined. So I can do that. You can see here I've got
some decoration going on, some bordering. So I could change this,
instead of saying border.all, I could just say, hey, just
draw the bottom border. And there we go. So OK, playing around with
this, this is nice, where-- I am way ahead of time. This is great. Chris, you're going to have
tons of time to talk after this. But this is pretty white
and it's pretty minimal. And that's nice, but maybe we
want a little bit more color in there. What could I mix into this? So let's go back, and here's the
code that I've written so far. I've got a number pad. I've got a dialer. I want to create
a new look dialer. So I'm going to
create a new widget. And I'm going to call this
my fancy dialer, because it's going to be fancier. And I can't spell dialer. That's fine. And OK, so let's
just start with, I want to show you
something in the background. So I'm going to create a stack. And you've seen row. You've seen column. You've seen table. Stack is another way of laying
out except you stack things on top of one another
rather than horizontally or vertically. So I'm going to create a stack. This stack is going to
take some children, which is going to be a list. And to begin with,
I am just going to drop in my dialer,
which I just wrote five minutes ago, into here. And then I can up here swap
out this to my fancy dialer. And absolutely nothing
is going to happen because at the moment, I'm just
showing the same thing before. Now, what I want to do is
I want to put something in the background. So I'm going to use
this handy position dot fill widget,
which is basically going to fill my background. And in here, I'm going
to put the Flutter logo. And I'm going to get
the commas right. There we go. Boom. So we got a Flutter
logo in the background. That's pretty ugly. Can't really see
what's going on. I am not a-- Will come up on
stage and show you how to build beautiful things. This is not what I do. I build things that
are functional. But this is too
ugly for my liking. So what I can do here is I
can take this Flutter logo, I can wrap it in a new
widget, and this one I'm going to give it
some transparency. So I can use this
opacity widget. And I can set the opacity
to, I don't know, say zero-- let's say a fifth. OK, it's not too bad. It's certainly not as
eye gouging as before. But it's still a little
white and minimal. So let's add a little
bit more color in. So how can I do that? Well, one of the
things I can do is let's say under the opacity--
so things are still opaque, but before we render
the logo I'm just going to style up the
container that the logo is in. So container takes
a handy decoration. And I know for a fact this
is called box decoration. And let's have a look. This is a whole bunch of things. I can do borders and I can
do box shapes and shadows. But I'm going to
play with a gradient. So let's stick in a gradient. And I'm going to give
this a linear gradient. And this is going to
require a couple of colors. And I'm going to stick with that
dark blue that we had earlier. And I'm then going to make
a hideous design choice and blend it into
green, because why not? And there we go. OK. So now we've got a color. That's kind of fairly opaque. So if I turned on the
transparency a bit, you can see a little better. There we go. That's nice. Don't quite like it
going right to left. Maybe I want it to go diagonal. So there's probably
something to do that. So let's have a look. Linear gradient, yes,
has a beginning and end. And notice that occasionally I'm
going in and putting in commas and that's just to lay
things out at leisure so I can drop things in again. This is the tooling at work. So what was I going to do? I was going to say
begin and I was going to align my
begin at the top left. There we go. So that has-- did that work? It's hard to tell. Let's try bottom right,
see if that does something. Oh, OK. We have a slight issue
here, or is it not updating? Let's double check. Whoops. Let's see if we can
go here and do that. OK. Oh, you know what? My phone's gone to sleep. There we go. I was going to blame
Flutter and it actually turns out it was my phone. And so if we go back to
green and we stick it at the bottom right, we're
going to have that nice effect. Bottom to top, great. So we have a
wonderful UI for a-- we have a UI that you may or may
not decide is wonderful for-- dear me-- for dialing. Now, does this actually work? Well, we'll see in a second. But what I want to show you is
something new in Flutter 1.2, which is before we had some
really good debug tools built into Android Studio. It was great. You could do it. Visual Studio Code, not so much. And I'm more of a VS Code
minimal IDE kind of person, so I was sad. But I'm no longer sad,
because what I can do is I can start the new DevTools. And in a web browser, it's
going to launch a suite of tools that you can use. So you can see this is hooked
up to my app right now. I can go in. I can go and see
what's my opacity. I can see it's a 0.5. I can check out what's happening
with my logo and where it is. I can drop down to--
so I can drop in and I can inspect the
widget tree easily. I can go in, I can
turn on my debug paint to work out how my
layout is looking. That's nice. And I can even do the
performance overlay. And as I'm using my app,
it's actually telling me what my frames per second is. So I'm easily achieving
under around 60 frames per second at the moment. So that's really nice. So these are available now
shipping with the beta or 1.2. And you can play around with
that, available across all the IDEs we support. So that's nice. So final test, I
actually wrote some code which hooks into the
Android and the iOS system for dialing numbers. And being an Android problem
before, that was easy. And being on iOS, I learned
a bit about Swift doing that. But what I did was I effectively
created some very lightweight code, thus platform specific. And then I built, using
platform channels, which is how Flutter can
communicate with the systems, to make that happen. So what I'm going to do is
I'm going to test this out. And I have a phone
number, which is Chris's. So you can take it
down and ring him. CHRIS SELLS: I thought
we agreed this was going to be Martin's phone number. MATT SULLIVAN: Uh, you clearly
didn't get the text from him last night. And so we are going
to try this out. OK, so now hundreds of
my new closest friends can feel free to call me
whenever you like, maybe at 2:00 in the morning you've
got a burning Flutter question. Hey, Chris, how do
I make this work? And this is a American phone
with a UK SIM sitting in Spain, so it takes a few
seconds to go through. Did I get your number right? [PHONE RINGING] CHRIS SELLS: Hello,
Mobile World Congress. MATT SULLIVAN: There we go. I think that's working. CHRIS SELLS: Excellent. MATT SULLIVAN: And there we go. So there you go. So that was a dialer in Flutter,
mostly written from scratch with a few bits and pieces,
in 16 minutes and 52 seconds. CHRIS SELLS: Thank
you very much, Matt. MATT SULLIVAN: All right. CHRIS SELLS: So it was
experiences like that that made me excited about Flutter. I've only been on the Flutter
team for about three months. And it was actually sitting
down and writing Flutter code and actually
experiencing exactly the kinds of things Matt
was showing for myself, building my own custom apps,
getting up to speed quickly, being able to use
hot reload, being able to actually write a
single hunk of source code and have it go across
multiple platforms. That's my real experiences. And I called up the team
and they had a spot for me. And now I work for Flutter. I mean, that was
pretty great for me. So I was explaining all of
this to another friend of mine, a software engineer at another
large software company. And I was telling him
how great this was and I could write my
code once and have it work across multiple
platforms, Android and iOS. And he looked at me and he said,
isn't that a solved problem? Can't you already do that? And I said, well, sure. And there's two main
ways to do this. You can write two apps. You can have two teams and write
two apps, one from Android, one from iOS. And that gives you the good
chance at good performance and it gives you access
to the native APIs. But you have two teams. And you have two code bases. And it's easy for the
features to get out of sync and for the
branding to get out of sync. And over time-- and we hear
this from our customers-- the apps get out of
sync with each other. That actually happens. The other way of
do it, of course, is there are existing
cross platform frameworks. You can write your code often
in JavaScript, in HTML, in CSS, and those are easy technologies. A lot of us are familiar with
those style of technologies. We can pick those up. But when you do that
and you actually deploy to production
environments, you have some
problems when you're trying to maintain
60 frames per second with tearing or scrolling
or garbage collection or jank or animation problems. You have these problems. And so the idea of
Flutter is that it is meant to be the best of both,
to take the native performance and quality and the high
velocity developer experience and combine that
with the ability to get to multiple platforms. And so we're going to talk
about how Flutter enables that, how Flutter, as
a modern UI framework, makes this happen. We're going to start with
talking about its architecture. We're going to
talk about what it means to be declarative and
composable and reactive. We're going to talk
about how it works well across multiple platforms
with a rich ecosystem, how it has first class tooling
and community support. And we're also going to
talk about its open source nature and the benefits
you get as developers using open source. OK, that's what we're
going to talk about. So of course any architecture we
want, we want it to be layered. We don't want it
to be intermixed. We want it to be easy,
if there's anything that we want to do
to extend Flutter-- either on top by
building our apps or in the middle by forking
it or adding functionality in between-- that you can do that. OK, so at the bottom of the
architecture is the engine. And this is built in C++ code. It's meant to be the fastest
possible thing it can be. So it's built at the low level
to do drawing and low level rendering. And we also have the
Dart runtime and jitter at that bottom level. Now on top of that, everything
else is built with Dart. When Matt was actually
digging through and saying, hey, I looked up this source
code in Visual Studio Code for one of the core
Flutter widgets, he was showing you the actual
source code, the source code that's available on GitHub,
and you can take a look at. And it's heavily commented
with documentation so you can understand and
extend it whenever you want. And so those are
the kinds of things like animation and
rendering and widgets and our set of components. And we'll talk more
about those in a minute. On top of that is a set
of plugins and packages. And those could be
written in pure Dart, or could be a mix of Dart and
Java, mix of Dart and Kotlin, mix of Dart, Java, and iOS
code, Swift or Objective C, the idea being that you
can have these plugins that have the native code
in them with a Dart API so that you can add them to your
app and call them from your app and not have to worry
about the native code. And we have a rich ecosystem. We'll talk about
that in a minute. On the side, we have
a number of tools. Matt mentioned
Visual Studio Code. That's his preference. But we also have Android
Studio and IntelliJ support, deep integration with
all three of those IDEs. You saw the Dart DevTools, which
is brand new for Flutter 1.2. We also have a full range
of command line tools, as well as at its core,
if you're running Dart, you're running an
analysis server. And this is what provides
the language services across all of these IDEs. And then we also have an
ahead of time compiler. And you might be
wondering, what possible use could we have
for a just in time compiler and an ahead
of time compiler? Why do we have both? We have both so that we get
the best of both worlds. While Matt was
writing his code, he was running a development build. He was running in a Dart VM
using the just in time compiler so that when he was making
changes and pressing the Save button, those changes were sent
over the just in time compiler and they were just
in time compiled. So that's why you get
that sub-second reload with the state intact. However, when you want
the fastest possible speed in a native environment, you
don't want a VM in the way. What you want is native code. And so that's what the ahead
of time compiler provides. When you target Android
and iOS specifically, that's what you get
the performance. No matter which
way you go, you are going to get optimized runtime
for building client UIs. Flutter builds a ton of objects
every time you make a change. And we'll see how this works. When you make a change
that causes a re-render, you're going to get a
new subtree of widgets. That's a set of objects. If it's a big subtree, it'll
be a big set of objects. And if you're doing
this 60 frames a second, it'll be a lot of objects
being created and destroyed. Dart is optimized for that. Dart as a platform
and as a language is optimized for
building client side UI. Now, when it comes to features
of a modern UI framework, first and foremost, we want
something to be declarative. This is something that
we have from the web. Traditionally,
before the web, when we wanted to, say, layout
something like what we have on the right there,
we'd say, OK, we have an image and it starts in the
upper left and it has a certain amount of width
and it has a certain height. And then the thing
that comes under it, we offset it and we layout that and
we calculate all those numbers and we lay it out ourselves. That's not how I
want to spend my day. With a declarative layout,
what you do is you say, hey, I've got a
parent widget and I've got some child widgets. And I'll tell you how
much space they need and what their layout
constraints are. And then you figure
it out, right? That's what we
want from Flutter. We want Flutter
to figure it out. So we declare our
intent and Flutter does all of that offsets and
all those positions for us. So here's an example of
code that Matt was showing. Start at the top,
work your way down. Here we've got
some custom widgets we're in the middle of creating,
that each one can easily map to the set of things
happening on the right. You can look at your
UI and write the code. Now, Matt said, hey,
everything is widgets. He spent all this time
bringing in widgets. He wanted a row
here, a column there. We have architected Flutter
to have a large number of small widgets. Those small widgets are
easy to understand and easy to compose, in different ways
that we've never thought of. But what they do is
they make it easy for you to combine
them in ways that you need to make your app work. And it encourages both
you and third parties that you get widgets from to
build small composable reusable widgets that make it easy to
understand and easy to reuse. That's how we've architected it. All right. I see we have a hand raised
for a question, which is good. I like to inspire questions. We are going to have a
panel afterwards where we're going to answer
all those questions. Great. OK. And again, this idea of
widgets all the way down, you might have seen
these words on us my slides earlier,
the difference between material in Cupertino. We have two main
family of widgets that are styled for
material design, or for the iOS apple
design language, which we call Cupertino. It's the set of widgets
that look and feel like material widgets
or iOS widgets. You can mix and match them. They work just fine together. You can decide that you
want your Flutter app to look like one or the other,
depending on what platform it happens to be running on. You can decide--
and this is what we see a lot of our customers
deciding-- that we want our app to have its own
unique look and feel, a branded look
that looks the same and works the same across
multiple platforms. Doesn't matter. All fully themable. You how saw how easy it was for
Matt to add shadows or change colors or add gradients or
change a box to an underline, change the icons. It's all that easy. You have full control. You can make it look exactly
how you want it to look. We also want it to be reactive. Modern UI frameworks
are reactive. Well, what does that mean? The idea of a reactive
framework is sometimes your widgets are stateless. They are completely composed
by the parameters that come in. Sometimes, however,
parameters have state. Matt showed this when he
showed that his number box had stayed in it, right? It was showing what the current
number was, as the user dialed. When a widget has state
and that state changes, the widget needs to update
the view of its self. But it doesn't go
and say, OK, draw. Or it doesn't do what the old
style UI frameworks used to do, which is, oh, you know, this
part of my UI is now invalid. Wait for some kind of a message
and paint that rectangle. We don't do any of that. All we do when we're going
to change some state-- for example, here we've
got a like button. And we've got-- is that
button currently liked or not? And then when we have
our build method, which provides this widget of
components that make up this button, when
we set the color, is it light, red, or white? We just use the state to
compose how that widget looks. Now, when the user
clicks on that control, we want to change whatever
it was to be the other thing. But we want to do it
in this set state. And set state is a
signal to Flutter that the state associated
with this widget has changed. And so it gathers up all of
the set state notifications and it's synchronized
to make sure that it's drawing as fast as it can. So it bundles some of them up
together as much as it can. And then it goes to the
widgets and say, oh, I understand you
have a new layout. And it calls the build method. And then the widget just
says, oh, well, here's what my layout is. That means that you
as a widget author only have to worry about the
state, both of the static state that came in when you
were built as parameters and the dynamic
state that can change during the lifetime
of the widget. And you use that to figure out
what your widget looks like. You don't have to worry
about is this the first time this widget is called? Is this the second time when I
have to make minimal updates? And the reason you
don't have to do that is because Flutter, when it
reacts to the set state call, will gather up what you
give it in the build method and then compare it to
what's already on the screen and come up with the
smallest possible delta to make the change. That's how you achieve
that fast re-draw, that 60 frames a
second, because Flutter is aware of what's going on. And it does all
that heavy lifting. And you just have to
say, in this state, here's what my
component looks like. And Flutter will react to that. Great. So, what does it mean
to be multi-platform? Well, we know today that
Flutter supports out of the box, as of December,
in production release, Android and iOS. How does it do that? It does it with something
called the embedding API. The idea is that
most of Flutter is completely agnostic to the
platform it's running on. But at the very
bottom level, there has to be a mapping
that says, oh, I want to draw a pixel on the screen. That happens differently
on Android versus iOS versus something else. Plus, oh, there's an event. Somebody touched
something or somebody moved a mouse or clicked
on a keyboard, right? Those kinds of things
are platform-specific. So there has to be a mapping. That mapping is called
the embedded API. What we've done on
the Flutter team is provide implementations
for both Android and iOS. We're also experimenting with
implementations for desktop, for Windows, and Mac, and Linux. And we're experimenting with
implementations for the web, with the idea that if you had
those, you could just say, I've got my Flutter code and I
want to target it at whatever embedding API I
happen to care about, or whatever implementation. As one example, one member
of the Flutter community happened to really
like Raspberry Pis so they built an embedded
API implementation for the Raspberry Pi. If you want to take
your Flutter app and point it at a Raspberry
Pi, today you can do that. You don't have to
wait for Google to implement that embedding API. You can do it yourself. OK, great. So that's one way we
support multi platforms. Another way we support
multi platforms is once your app is
running, you need to be able to call
APIs sometimes. When Matt was making
his dialer, he had a nice little dial button. In the background,
that dial button had to do different
things based on whether it was running in Android or
whether it was running on iOS. Because how you dial,
there's just different code. And you bind to different
libraries, right? That's just how that goes. The way we do that
in Flutter is we do something called
a platform channel. The idea of a
platform channel is, this is your Dart
code that sends a message to some listener. And that listener is going to
change based on whether you're running on Android or iOS. If you're running on Android,
it's the Android listener. And it will take that message
and call the right native API and package up the
response and send it back. If it happens to
be running on iOS, you'll have the iOS listener,
and it will do the same. Whenever you want to get to
the native APIs on whatever platform you want to
target, you can do so via platform channels. OK. Now, that platform
channel idea has led to a whole
ecosystem of plugins, because the idea of a
plug-in is Dart code plus platform specific code
for one or more platforms. A package, a regular old Dart
package, is just Dart code. But a plug-in is a
piece of Flutter code that can target the native
platform using those platform channels. And so if you want to write
that native code, you can. But if you don't want to, you
can just go to that URL right there and type in a
search word and see if one of the 1,400 components
that's already there serves your needs. And the Flutter team has
put a bunch up there. And other members of Google
have put a bunch there. And there's some great ones
from the Flutter community. And Square has built one. And Firebase has built one. A couple of new ones that are
pretty popular, the web view, being able to host the browser
inside your Android or iOS app, or Maps. The things you would expect
from Google are up in that list. So what about tooling? What about the community itself? Well, as Matt mentioned,
we support Android Studio and IntelliJ and VS Code. It used to be before today that
Android Studio and IntelliJ got a little more love. That cool inspector code that
Matt was showing, that only ran inside of Android
Studio and IntelliJ. But as of today, with the
Flutter 1.1 or 1.2 release, we've made it available as a
separate standalone application so that if you happen to be
using Visual Studio Code, we've integrated that. It works just fine. Or if you want to use it
from the command line, you can do it that way, as well. So you can use whatever
editors, whatever IDE your little heart desires. We support them all. We also saw Martin
showing off code magic. I'm a big fan, being able to-- it's so amazing being able to
make a change to your GitHub, and then, boom, magic happens. That's where that
term comes from. Excellent. All right. Also, if you haven't seen
Flair by Two Dimensions, this is a standalone
animation tool where you can build animations,
and see timelines, and watch things go and tweak things and
bring in your graphics and all the things that you expect
your designers to do with their animation tools. But then you save the file. And you pull it up
in your Flair code. And you have these
interactive experiences in your Flutter code. As I mentioned,
we have the IDEs. But if you don't
like the IDEs, you can feel free to
use the terminal. All that functionality is
available from the command line. We like everyone on
the Flutter team. As I mentioned, also, Flutter is
open source, fully open source. All the stuff, that whole
architecture, all the stuff I showed you on there,
it's all open source. Feel free. We have hundreds of
contributors, lots of which make significant contributions. In fact, several of the features
that we're announcing today in Flutter 1.2 come directly
from third party contributors, not just the Flutter team. And in terms of
momentum, we've shipped the 1.0, as I
mentioned, in December. We've already doubled the
number, almost doubled the number of developers,
in that time, in 10 weeks. It has been amazing to watch
the growth of the number of developers on Flair. We've seen a 40%
increase in the number of plugins, Flutter-specific
packages and plug-ins. We're in the top 20 now on
GitHub when it comes to stars. We're right nestled nicely
between Node and Go, which is a pretty nice place to
be for a pretty young project. I won't say which
one we're ahead of. I'll let you look that up. Thousands of apps in both app
stores, and great community support. If you want to get started,
reddit, Stack Overflow, the chat apps that
you might like. Where you want to
ask questions, where do you want to get questions
answered, all of that-- flutter.dev/community is
a fabulous place to start, as well as startflutter.com,
flutter.institute, online training that you
can just use today to learn Flutter. And they'll take you step by
step through what it takes to be a Flutter developer. And of course, I
mentioned open source. And not just open
source, but open source with frequent updates. And of course, I
mentioned a couple of times Flutter
1.2, which comes with a number of
framework features, including animation easing
functions and Android app bundle support. And as I mentioned, those
are from third parties. Those don't come from
the Flutter team. Two big features-- new
Cupertino theme that gives you even more control, and
keyboard and mouse input as we expand Flutter's
reach, for example, to building great tablet
apps or great Chrome OS apps where mouse and keyboard
is a part of the input and not just touch. We're building that right
into the core of Flutter. And we've got more
work to do there. We're doing a number
of localizations. And from the tooling
side, Matt already mentioned Dart dev tools. We are adding
support for Java 1.8. And we've done a
bunch of studies in terms of error messages. We've found that with a
little bit of user experience research-- we've got an
amazing UX team, by the way, on Flutter-- that if we can change
the format and the text of the exact same error
messages you already get, we can make you something like
50% more effective in terms of actually being able to
act on those error messages and fix them. That's amazing. So we are pushing on that. And we're going to
continue to push on that. If we can make you more
productive in any way, that's what we're going to do. OK, and let me show you
another couple of others. You saw Dart DevTools. Here's another one. We've noticed that
a lot of folks like the samples that
come with Flutter. But the way we've got
them arranged right now, they're kind of embedded
inside the Flutter repo itself. And that's great for us
because it makes sure that when we change things, if
there's problems and breaking changes, we see
them in the samples. So we want to keep it that way. But it also makes
it hard to extract if that's all you want
is one sample, as opposed to the entire Flutter
source code base. So now we've made it so
both within Visual Studio Code and Android
Studio, IntelliJ, you can pick which sample
you like and base your work on that sample. It's great for just
looking at the sample and learning Flutter. It's a great base. Recommended. Another one--
remember I said, hey, we like all the
developers of all kinds? We want to support all IDEs. How many vi, Vim programmers
are in the room, Vim users? Couple? Uh oh. Let me ask the other question. Emacs? Uh-- I don't want
to start a riot. And not everyone
raised their hand. Is not everyone using
either Vim or Emacs? Are you using
something different? I assume-- yes, one person
is using something different. Excellent, thank you very much. Thank you very much, sir. Anyway, for those
of you who like Vim or other editors besides
IntelliJ, Android Studio, or Visual Studio, we're
actually releasing an alpha of a language server
protocol implementation in this release so that you
can plug it into your existing editors, even if
we don't support them directly with all that
functionality if you want to. And in this particular
case, we happen to be reflecting an error
message of some dead code. But we can do warnings
and finding definitions and references and refactoring
with renaming and all the goodness that LSP
provides, the idea being we want floater to be
everywhere, and that includes developer tool support. If I have excited you about
Flutter as much as I am excited about Flutter, I would
like to direct you to flutter.dev/create-- the Flutter team's
first coding contest. The goal is, how cool can
you be in five kilobytes of Dart code or less? And if you want to
remove the comments and use really short variable
names, I won't complain. Feel free, OK? So check that out, the
Flutter create challenge. I think the top prize is a
monster Mac, like desktop, huge Mac with a big monitor
and all the trimmings. So if you're excited
about Flutter, I definitely recommend this. That's what I had to
say about Flutter. As always, Flutter.dev
is the place to start. And thank you very
much for your time. [APPLAUSE] [MUSIC PLAYING]