Google I/O 2011: Using GWT and Eclipse to Build Great Mobile Web Apps

Google I/O 2011: Using GWT and Eclipse to Build Great Mobile Web Apps

Ramsdale: Thanks for coming out. Welcome to day two
of Google I/O. I hope you enjoyed the, uh,
the great keynote on Chrome. Uh, and thanks for coming
to this session. Today, we’re talking
about using GWT and Eclipse to build great mobile web apps. My name is Chris Ramsdale.
I’m the product manager for GWT and the Google Plugin
for Eclipse. So let’s get right down to it.
Let’s talk about why we’re here, make sure you’re actually
in the right room. I’m assuming so.
Um, by a show of hands, how many people actually have
a GWT application that they’ve built
or that is in production today? All right, great. So chances are,
there’s plenty of people that are building web apps
in the audience today, and as many developers are, you’re interested in doing
something in mobile. So actually, we’ll do that, too.
So a show of hands– how many people are interested
in doing something in mobile or are doing something
mobile right now? Great, fantastic. So, um, as developers, we like to create
efficient applications, right? Ones that run fast. And also as developers, we like
to be efficient ourselves. So chances are,
you started with GWT. You have a web app that you’ve
built. You’re happy with it. Maybe you have several of them.
You have a code base. You know,
you have several thousand, tens of thousands,
a million lines of code. Wouldn’t you love to reuse
some of that code when you go to mobile? And also, wouldn’t you
like to get around some of the friction of getting
to mobile in the first place? So let’s talk about that. So some of the friction
or some of the problems associated with going
from, uh, say, a desktop web client to doing a mobile web app
are these. Mobile typically has
smaller screens, right? And not to mention,
not only are they smaller, but they actually are different. So you have tablets,
and you have phones, and you have TVs. And now you have, uh,
Android running on workout machines,
so who knows where it’s going? Someday, you’ll be running
an application on your toaster. They have smaller screens,
and they’re different. You can break it down
even further, that while they have
different, smaller screens, they also have
different orientations. You see this most predominantly
with, uh, tablets. If you take a look
at GMAIL today, GMAIL in landscape–
uh, landscape mode looks different than GMAIL
in portrait mode. They typically have
slower processors. While they’ve been on the rise, tablets and phones still lag behind laptops and desktops. And then finally, the one that,
uh, concerns me the most is that there–
they can be disconnected. In fact, you expect them
to be disconnected. They–they are portable devices. I need to take them
wherever I go. I expect to be able to use them
wherever I go, whether I’m in a subway station,
a subway tunnel, in the middle of Kansas, on the flight I took
to Minneapolis to get here, where I had no Wi-Fi. I expect to be able to use
my applications. And typically, that’s easy to do
with installable mobile apps. You don’t see it as much
in mobile web apps, so we’re gonna talk
about how to get past that. So those are the problems. So I wouldn’t just leave you
with a bunch of problems. That’s why you came
to this I/O session. I should give you
some solutions, too, right? That’s the whole idea.
You want to learn. So today, uh,
as indicated by the title, we’re gonna talk
about how to use GWT And Google Plugin for Eclipse
to build great mobile web apps for iPhones and Android devices. And specifically, we’re gonna
focus on how to build great UIs for any form factor, and we’re gonna talk about how
to optimize the user experience. We’re gonna talk about how
to make it snappy, make it fast, right? ‘Cause after all,
installable web apps– the one leg up
they have on you if you’re developing
a mobile web app, is that they’re really fast. They happen to run a little bit
closer to the metal than when building
a mobile web app. We can get around that. Then finally, we’re gonna talk
about working without a connection–
how you would do that. [clears throat] So to–to drive us
through this session, um, we have a sample app, and it’s available, um,
as part of the GWT 2.4 beta SDK that we announced yesterday. Um, and specifically,
it’s–it’s a– it’s a standard application
that’s web-based. It’s a web-based
task management application. We have UIs for Android,
iPhone, and iPad and desktop browsers. We show you how to do
orientation change handling. We have offline support. And we’re gonna run through
some of the key pieces of that application
in this presentation. And I’ll keep bumping from code to actually running
on the device. Then we’ll show it
pulling all together at the end. So let’s jump right in.
[clears throat] Talking about building great UIs
for any form factor. So if you’re gonna have all of these devices that
you’re gonna support, right? Then you’re gonna have to write
different UIs for them, right? And it’s really not that–
that much coding. We’ll get to that in a second,
but you’re still gonna have to write different views,
different UIs for them. We should make it
as easy as possible. So the nice thing is
that with GWT– and these are
our existing features– But with GWT, we have—
if you choose to do it by hand, to code it by hand, we have
a feature called UiBinder, which makes it very easy to do
declarative UIs inside code. So what does that mean to you?
That means that writing UIs is no longer orthogonal
to what you’re used to. So if you came
from a web-based background, � la coding in HTML,
JavaScript, and CSS, you can use UiBinder,
and you feel warm and snuggly, like you’re at home. Um, then if you choose
to not do it by hand, and you’re a lover
of developer tools, like we are on the GWT team, um, you can use GWT Designer, which is now part of
the Google Plugin for Eclipse for doing, you know,
UIs in a WYSIWYG tool. So taking the UiBinder route, again, the focus here
is to how to make it easy to create multiple UIs
with very little friction. So here’s an example
of a UiBinder template. I’ve stripped out
some of the code here for demo purposes, but again,
it’s all available at the end. So we start looking
at a UiBinder template, and the first thing we see
is that, one, it’s XML, so it kind of looks like HTML.
That’s good. Um, and we immediately jump
into style. So in this case,
I’m highlighting the fact that we have a style
for addButton. So that’s gonna be
the little plus icon that I’ll show you
in just a second. Uh, some simple styling–
give it a color, a font size, a background,
border, so on and so forth. And that’s all wrapped up
in that widget. So, one, it’s easy to see.
So you just open up one file, and you can actually see
your styles along with your, uh,
the declaration of your UI. And then, two, those styles
are only for that widget. So you get no pollution
of the global namespace, which is, right, really nice. So now that
we’ve got our styling, let’s jump into the actual
layout of our application. So what I’m walking through here
is the main screen of the–the task application. And, um, again,
it’s a few details omitted, but you’re gonna get
the general idea here that we’re walking through
and we see first off that we have the header,
the title of the application. And the way we’re laying
all of this out is using a DockLayoutPanel,
which is a GWT widget. And that gives you the north,
south, east, west region of your application. So in the north, we’re gonna put
the title of the application. That’s this. Then we’re gonna drop down
into the left-hand side, the west side–
“west side”– which is gonna be the, uh,
the task list, right? It’s the actual list of tasks
that you’re gonna click on. That’s this. And then finally we come, and we
give it the content, right? This is the content area.
It goes in the center, and that’s gonna be this, right? So that’s it.
That’s how you– That’s how you start
constructing this. Now then behind this is a bit of
Java that’s gonna run it, right? That’s gonna
actually feed it data and actually populate
all the UIs and everything. But when it comes
to constructing the UI, that’s the bulk of your code
right there– to write this. So then let’s say, again, that you don’t want
to do it by hand, but instead, you’re gonna
do it with tooling. What you can do is you can
drop into our GWT Designer. So this is the same, uh,
the same view, but brought up in GWT Designer. And what you can see
is that you’ve got the title. You’ve got your header, and
you’ve got your “add” button. And then on the left-hand side,
you have a list– you have a set of widgets. You have all of your panels
that you can drop in there. You have buttons.
You have lists. You have cells. You have tables. You have labels
all at your disposal to start editing this–
this UI. And then on the right-hand side, you have the properties,
for each of those widgets. If you want to change the color, if you want to change
the name of it, if you want to change
the class– the Java class that backs it,
you can do that here. So again, after doing this,
what you end up with is two different UIs, right? You’ve done it in a very,
very limited amount of time. So you have your ListView
for tablet, and you have a ListView
for phone. Notice they look different.
So this is just the beginning. This is just how you start
getting going, right? So you’re basically–
we’re starting at a ground zero, acknowledging that we need
to have different UIs for different devices, right?
For the best user experience. So, great, that’s fantastic.
I probably haven’t told you too much that you don’t
already know, ’cause you’re already
writing UIs and using GWT. So let’s move on
to the more meatier parts. So how do we optimize
the user experience? So now that we have
these different UIs, how do we pull the right one up
for the right device? [clears throat] So–and it’s–
it’s more than that. It’s not only how do we pull
’em up for the right device, it’s once we have pulled up
the right UI, how do we handle
orientation changes, if we’re running on a tablet
or a phone– in this case, in the demo,
how to do it on a tablet. Um, and then we’re
also gonna talk about the icing on the cake. So this is a–if you’ve gone
through this process, and you’ve created
different UIs, and you have a way
of selecting those UIs and serving them up, um,
and what–what you end up with is a–is a design pattern that
works very well for code reuse and actually looks
a lot like MVP. So we’re gonna talk about how
you can get maximum code reuse when creating, uh, desktop, tablet, and phone applications. So let’s jump in right here. So talking about,
uh, how to– how to select the right UI
per device, and we’re gonna use deferred
binding to sort them out. Now if you aren’t familiar
with GWT, or you haven’t kinda dove in
a little bit deeper, you might not know exactly
what deferred binding is. We’ll do a little recap. So at the heart of GWT
is this notion of being able to generate
a browser-specific version of your application, then serve that up when
that browser selects it, right? So you get
the optimal application. It’s called deferred binding,
and what ends up happening is the browser makes a request,
and through some configuration, we end up picking out the best
UI for, say, IE or Firefox or Chrome or Safari. Well, lo and behold,
that works really, really well for mobile devices–
mobile devices, as well, right? So you can say,
Well, I want to– I want to serve up
an Android phone-specific or an Android tablet-specific
version of this application or a iPhone-specific
or an iPad-specific– You can get as fine-grained
as you want to. [clears throat]
But for the sake of this demo, let’s just talk
about how we could serve up a phone versus a tablet view.
We’ll dig into that. So I mentioned
this GWT module config file, and it’s really just
an app configuration file for your, uh,
GWT-based application. In this case, I’ve got
CloudTasks.gwt.xml. And inside of that file is
a whole bunch of properties, um, that are
for your applications. So it’s where you–you define
all your dependencies. It’s where you might actually
define your entry point. And then the other thing you do
is you define some of your deferred
binding properties, right? So in this case,
what I’m saying is, um, as a developer,
I want a ViewFactory, right? I want a factory that’s gonna
serve up my views, and that’s an interface
that I define. Um, and I have different
implementations, right? So for mobile, I have
a mobile implementation of it, of that factory. For a tablet, I have a tablet
version of that factory. And then what ends up–
what ends up happening is that, um, those are
selected for me under the hood, and it’s done with, uh,
deferred binding properties. And so in this case, it says
when the form factor is mobile, give me the mobile version
of this–of this ViewFactory. Then I can say give me
my ListView, and it’s actually the ListView
that’s optimized for the– for the mobile phone device. Subsequently, I can do that
with tablet, too. It says, okay, when I– when a tablet is requesting
my application, give me the ViewFactory
that’s specific to that– you know, that type of device,
that form factor. Give me the tablet version
of the ViewFactory. [clears throat]
So this is great, pretty easy to understand
and to digest. But I keep saying
“when the form factor is,” “when the form factor is.” So what actually is
going on there? So, uh, under the covers,
what’s happening is, uh– if you’ve ever
written JavaScript, you’ve–you’ve seen this,
I’m sure. Uh, we’re simply looking
at the user agent and looking for the existence
of, say, “ipad” in this case. And if we see “ipad,”
we’re gonna pass back that it’s a tablet. If we see that it’s an iPhone,
we’re gonna pass back “mobile.” And then if we see “android,” there happens to be
a little more complex heuristic for figuring out whether it’s
a phone or a tablet. but the fact of the matter is
as complicated and overly complex as that is,
we just hide behind– we hide it behind
this set of codes, so all your doing is writing
code that looks like this. Look–when it’s a tablet,
let me know and give me the right– give me the right implementation
for this interface, and then I’ll go call–
I’ll go call and– I’ll go make calls on that
implementation that I get back. Good. So now we have
this model sketched out to where our browser
can make a request, and we can get back
the right ViewFactory for the phone or the tablet, and now I can pull together
these views so that when I get back, say,
the tablet version of my ViewFactory, I’m gonna pull my ListView
tablet.ui.xml file. That’s how I get to that file.
That’s the path. Same goes for the phone. And so then we can actually
see this over here. Ramsdale: Can I get
both of ’em on here? Ramsdale: Good. I’m gonna have to change
my key combination after that. [laughter]
Ramsdale: [clears throat] All right. That’s up. That’s up. [clicks tongue] Ramsdale: Cool.
[clears throat] Um, I’ll move ’em over
a little bit. But there you can see it
actually happening. So I just showed you
that those two devices actually selected
the same application. You can see the URL there and kinda there. But I get served
with two different UIs. I mean, they look similar, because my application
is doing similar things, but you actually get
different UIs. Ramsdale: All these clickers. Okay, so now that we’ve managed
to pull up a tablet-specific version
of the UI, how do we go from,
um, just that to responding to,
you know, orientation changes, so when I flip it from,
say, portrait mode to landscape mode? Um, and this is actually
much easier than you would imagine. So all you have to do is, uh, somewhere in
your initialization code you go back and say,
okay, uh, window– the window
that I’m attaching to– I want to add a resize handler. There’s several ways
of doing this. This is hap–this is how
we happen to do it in GWT. And you’re literally saying
when the window resizes, let me know, right? And inside of there, you’re actually keeping
state of where you’re at, like, am I portrait
or am I not? So if you go and you calculate, well, am I switching
from portrait to landscape, which is a very simple method
like this, is my client height greater
than my–my width, right? So if my client height
is greater than my width, then yes, I’ve gone
into portrait mode. And if–if the result of that
isn’t what I’ve cached, then I’ve switched from portrait
to landscape or vice versa, in which case,
I do adjustOrientation. Now we could jump into
the adjustOrientation code here, but it’s very
application-specific. But the net-net is inside of this code, you’d
simply, maybe hide a widget, right? So you might, when you go
from landscape to portrait– you might hide
the left-hand side– I’m sorry, you might hide
the content, right? And show just the list, and then vice versa when you go
from portrait to landscape. You would show the content and then minimize
the width of the list to adjust to the screen
real estate. Ramsdale: [clears throat] Then we see that happening here,
and it’s actually quite fast, so I’m pretty impressed
with this. Ramsdale: Notice that they’re
the same. [chuckles] All right, so here,
we have it in, um, here, we have it
in landscape mode. And then if I simply turn it, give it a little nudge, give it a little nudge.
There we go. So you can see that we pop
right back in there. And we literally–like, the–
the pause was not our app. The pause was the browser. So if I flip it around… Ramsdale: Come on, browser. Ramsdale: Do now?
There you go. Ramsdale: So once the browser
starts to switch, our application switches
quite fast. There’s no delay
in the application. Ramsdale: All right,
so now that we’ve talked about how to, uh,
create various– create different UIs
for different devices, how to select those UIs, let’s see some of the benefits
that we can get out of this, right? So this goes two ways.
If you’ve already– if you’re starting
to go down this path, you’re gonna end up
in probably a mode that looks like MVP. I’m gonna describe
what that is in a second. Or if you happen to be
an MVP developer already, you can take advantage
of these practices. But here’s a little recap
of–of what MVP is. So…
[clears throat] Um, it’s a–
it’s a design pattern. So it’s a Model-View–
Model-View-Presenter. That’s what the “M” the “V”
and the “P” stand for. Design pattern–
it’s very similar to MVC, Only you’re gonna have a little
less logic in your view. Um, all your business logic’s
gonna go to the model and the presenter. You want to keep the views
as simple as possible. And what we’ve been advocating
for the past year and a half, almost two years, uh, is that this leads
to faster test cycles, right? ‘Cause basically, what you
can do is you can run all of your tests and–
most of your tests as vanilla J or E/JUnit tests versus running in, say,
Selenium or using GWTTestCase to actually run your–
run your, uh, application in, say, like,
a headless browser. So this has been
what we’ve been advocating. Um, and this is really good. What I really like is
when you can take this pattern and apply it to mobile, because what ends up
happening is– so whether you have
a tablet versus a phone– and it could actually be tablet
versus phone versus desktop, right? The business logic
does the same. If I’m creating a ta–
a task application, like, that’s really not
going to change that much if I’m talking about one device
or the other, right? If I’m doing an e-mail
application like GMAIL, I’m just still giving you
your e-mail. So that business logic
stays the same. All that changes are the views, which we’ve already
talked about. So what you end up with is a–
is a pattern that’s ideal, right? You’ve already broken up,
like, what my model is, and then I’ve got my–
my presenters for a bit of my application
logic, my business logic. And then you’ve got these little
views over here that change, so it’s an ideal design pattern for supporting multiple
form factors. [clears throat]
And if done right, what you end up with
is, uh, code– if you were looking at it
from a high level– that breaks down like this, and
I’m talking about size of code. So you have
all your business logic, which is your presenters. That–you know, the presenters
are driving the views. And then you have your model…
[speaking indistinctly] your DTOs, your RPC,
your caching, your validation. And then that little part
over there ends up being your views, literally ends up being
your factories, right? They can give you back
your ListView for a phone or your EditView for a phone
or your EditView for a tablet. [clears throat] And then to tie it
all back together, that little piece
is really just is what– what’s changing in this deferred
binding property, right? So as you go and you say,
Okay, now a tablet has hit my– has hit my, uh,
my–my application, I’m going to give back
the tablet form– the tablet ViewFactory, and that is that little piece
down there that you’re serving up. So you end up with–
and then that’s the way you get past
the original problem, which was that I happen to have
a lot of code already, and it’s for a web app, and I want to do
something on mobile. Boy, it would be nice if I could
use that code over again. This is how you do it. And how you go about doing MVP–
we won’t get into that today. There’s plenty of documentation, um, on the GWT code site. The community has been very,
very active about doing it. There’s, I mean,
a handful of projects that actually, uh,
talk about how to do this. And so I’d advocate you go
out there and check those out. Ramsdale: So now let’s talk
about how we can make it snappy, how we can make a mobile web app feel more like
an installable app. Ramsdale: [clears throat] So we look at it–
what is the problem that people that are
doing mob apps– mobile web apps–
what do they face? Um, well, the first problem
is that HTTP requests on a mobile device
are quite expensive, right? Even on 3G, and especially if you get
onto an edge connection, a degraded connection, there’s a lot of overhead with
setting up the HTTP request, making it, waiting for it
to come back. We have to get around that. And then you want
to minimize startup time. And this goes back
to what I was talking about when you say that, um,
laptops and tablets have slower processors. What ends up happening
is you take a lot of, um, you take a lot of JavaScript,
you know, like 500k or a meg, and send it down the wire. Uh, it takes the–
the processor has to go through and parse
all that JavaScript, right? Load it up into memory, and what ends up happening
is that, you know, the parsing ends up taking time, which ends up degrading
the user experience, which ends up draining
the battery life– draining the battery, right?
On the device, ’cause you’re constantly
parsing JavaScript and–and, um,
and spinning that CPU. So there are
some solutions to this that are specific to GWT. So if you want
to increase responsiveness, um, what you can do
is you can minimize the number of HTTP requests
that you’re making, right? You can–you can bundle
all of your resources together so that you go an fetch them, so it’s one HTTP request
to get, like, let’s say 20 images or 20 images and 5 CSS files and so on and so forth. You can minimize startup time
by using code-splitting, so that–code-splitting
is just basically lazy initialization
of JavaScript. So you can say
I have a big app, but when I get
to the “Settings” screen, then go fetch the view for
my “Settings” screen, but don’t get it
on the front end, because I don’t really need it. And then overall,
while you can kind of move the fetching
of JavaScript around, what you want to do is– overall, you want to reduce
the amount of JavaScript that you pull down
in the first place, right? And what’s–this is where GWT becomes a perfect match
for doing mobile web apps, because, I mean,
we’re built upon taking Java and compiling it down
to highly optimized JavaScript, right? And we’ll talk
a little bit about some techniques
that we use to minimize
the overall output. [clears throat] So I’ve got a demo
to prove some of this. Ramsdale: [clicking tongue] Ramsdale: It didn’t like that… at all. There we go. Okay. So this is not part
of the sample application that I’ve been building up, but I wanted to pull it out
for the–for the sake of, uh, sake of discussion
and to make a point here. Um, it’s a simple application
that’s running on, uh, on App Engine right now. And what it is
is, uh, an application with a title and a button. And when I click on the button, it’s gonna go fetch
and bring up an image dialogue. So one could imagine
that if you were actually going to apply icons
to your tasks, or you want to tag them
with something like, “This is
the grocery store list,” or “This is the, uh, the lunch with, you know,
my colleagues,” you know, this is how you would
pull up that dialogue. And to give you an idea,
this is really what it does. So I will go through
what is going on on the bottom in a second. But as you can see,
it simply pulls up, in this case, 16 images. So let’s do this. Let’s clear this guy out. And what I’m gonna do
is I’m gonna walk through the waterfall
of HTTP requests in three different fashions. There’s the “Okay,
almost subpar way of doing it,” where you don’t do anything. There’s the better, where you
start to bundle things, and then there’s the best thing
you can do, which is bundle it
and then code-split it. If–if that doesn’t
totally make sense, just bear with me here
as I walk through each piece, and I’ll describe it
in more detail. So to make this real, let’s go and clear out
my cache, right? Ramsdale: And if anybody’s
asking why I’m using Firebug, it just happens
to have a better UI for showing off
what I’m about to show off. Feel free to use ChromeDevTools, but this really drives
the point home. Okay, so I’m completely clean, nothing in my cache. Um, no magic tricks going on. And what I want to do is
I want to refresh my app. So I’m gonna show you
what happens as you go from refresh
to button-click. All right. So, uh, a little bit
about what happens when you do a GWT application. So the first thing
you see is, um, we fetch the HTML page. And we look through it,
and then we go, and we see that, “Oh,
we need a style sheet.” So we go fetch the style sheet. And then we see that
also in that HTML page, we–we need the actual, uh,
GWT-specific JavaScript which can go fetch
the right permutation. That’s this nocache.js. Note that it’s only 2.5k.
It’s quite small. And then you see
this really weird md5 hash down here–
sorry, right there. md5.cache.html– that’s actually
all of the JavaScript for your application
bundled up in there. And you can note that this is,
you know, 19k. So it’s not huge. I’m not
showing you a huge application, but that’s where all
my app logic’s coming down. So that’s not too bad.
I mean, that’s pretty fast. Um, what ends up happening– let’s pull this up. I’m gonna clear this, and then
when I click on the icon… Boom. All right. So again, I’m on
an Ethernet connection, so it’s gonna be pretty fast,
but let’s pay attention to the waterfall graph
on the bottom. You see that I go, and I fetch
every single image, one by one by one by one. Um, and it’s really
not that bad. I mean, it was pretty snappy.
You probably saw a little bit of delay
as it kind of got one in and then put it up
on the screen. And you know, if you refresh it,
they’re gonna be cached anyway, so it doesn’t matter. But this is on
a desktop browser, right? And so you see–
I go fetch every image, and Fire–and Firebug does
a pretty good job of breaking down what is–
actually happens with each request. So you can see the purple
is waiting, right? And–and then the gray
actually is receiving. And then the–
the one on the left-hand side is when you’re actually blocked. So I spend quite a bit of time just waiting
for the HTTP requests. To make matters worse–let’s see
if I can pull this off. Switching around– yeah, great. So to make matters worse, um…
[clears throat] when you’re on a mobile device– so here’s the difference
between desktop browsers and–and mobile browsers. The number of
concurrent TCP connections great–is greatly different,
right? On–on modern browsers, you can get 10-plus
concurrent connections to the same domain. Um, on Android devices– and this came
from our page speed team– uh, great guys– you–you get four
concurrent TCP requests. Now that’s changing.
It’s getting better. With Honeycomb, they’ve–
they’ve upped the number, but, you know,
when you’re still catering towards Froyo and Gingerbread,
2.2 and 2.3 devices, this is what you get. So, um, four at a time–
you–you’re gonna start to see that graph that I just
showed you over here, you know, looks a lot worse,
because you see how I’ve done everything
concurrently down here. That gets broken up, so it gets
even worse for mobile devices. So how can we make that better? So I alluded to the idea of
bundling up all these resources, so we could take
these 16 resources here and bundle them up…
[clears throat] and then just go
fetch ’em at once. So let’s see
what that looks like. So again,
let’s clean everything up. No sleight of hand.
Clear. No, no, come back. Come back. Okay. So now I have
my snappy application. Okay, so what I’ve done here
is I’ve bundled all these up, and we’ll–
we’ll see the difference. Ramsdale: Okay,
so I go and fetch, and–and the–the mode
of getting the actual files and the files that I fetch
are exactly the same. I get my HTML page. I scan through it.
I get my style sheet. I go get my nocache.js,
and then I get my application, right? But now you can see
that the md5 hash, my actual application, went from 19k to 177k, right? ‘Cause it’s got
all those images. Now to prove that out,
if I clear this– oh, sorry,
before I jump to that– so note that it’s 177k. And let’s see, The wait time
was 400 milliseconds, right? So it’s–it’s very similar to
what the wait time was before. So really what I’m paying for
is the receive time over here. Sorry. If you can see it… Receive time–
446 milliseconds, because it actually fetched
all those images. And to prove that it fetched
all those images, look what happens when hit
the “Select Icon” button. All I’m picking up–
and look at the sizes. They’re very small.
But all I’m picking up are some–some artifacts that are used by, um,
our own styling, you know, like borders,
or clear.cache.gif file. Um… [clears throat] but you know, talking 433 bytes,
1.5k–nothing that big. And you saw how fast
it popped up, too, because it already had
all those images. It’s great. So real quickly, let’s look
at how we would do that. Ramsdale: So to do this, we–
we can enumerate all of our, um, we can enumerate
all of the resources in our application,
put those into an interface– the interface is something
that extends ClientBundle. Again, for
the complete documentation, definitely go check out
our dev guides in our Javadoc. But what we do
is we annotate this, and we provide a method,
so I can call, uh, you know, image0– so I can send
“resources.image0,” and I will get back
the image resource for my, uh, of my file. And I can do that
for all 16 of those images. And then when
the GWT Compiler runs, and the code generators run, we go and fetch
all those resources, we package them up
into one data file, and then we basically
do spriting over those data images. But the problem is–
let’s see this again. Ramsdale: The problem is
that now that I’ve fetched all of my images, I’ve fetched them
on the actual app startup. So especially
on a mobile device, this–this is gonna be
a huge time-suck, because I’m gonna
have to go– and, like, when I initially
hit the application, there’s gonna be latency there. So while the rest
of my application operates very smoothly–
and by the way, imagine this not with 16 images,
but with, like, 1,600 images or 160 images, something
more like a real app. And all of a sudden, it’s gonna
take, like, ten seconds for your application
to load for a user, or 20 seconds
for the application to load, and that’s just a real poor user
experience when they start up. Not to mention, you might not
even use any of those images. I may never actually use
your application and slipped on the button
that says “I want to add an icon
to my–my task.” I just don’t care.
[clears throat] So how can we make that better? What we can do is
we can code-split it. And again… Ramsdale: What I’m gonna do
is I’m gonna say, All right, I want to bundle
the images, but only fetch them when the user actually clicks
on the button. So we go and we refresh
the application. Again, everything looks
exactly the same, except for now when you look
down at my md5.cache.html, it’s gone down to 12.5k,
which is fantastic. In fact, it’s even better
than when we first did it, because when we first ran
the application, it was at 19k. So not only have I
code-split out all the images, I’ve code-split out the code
that actually loads the images, and so my–my startup time
is even faster. And… [clears throat] then when we go over here to do the selecting
of the icon… Ramsdale: Boom,
we get ’em right away. So now you can see
that I’ve fetched, so there’s–
there’s the fetch of the– of–of the data bundle, right? It’s 167k. And I’ve deferred that
to when I clicked on it, but I’ve still–
I’ve still bundled it, so that I minimize
my HTTP requests, and I end up only waiting,
you know, again, 358 milliseconds here, and my receive time
is 130 milliseconds. Again, very fast times,
but when you’re on, uh, I’m on Ethernet. When you’re on
degraded connections, say Edge, it matters. When you have more than 16
images, it matters, right? When you have an application like some of our
internal applications, some of your applications,
as well, where you’re up to, like,
let’s say, a meg or 2 megs or 3 megs
for your initial fragment, that’s gonna result
in a very, very poor user experience
on a mobile device. So what you can do is
you can cut that out. Ramsdale: Oh, I skipped–
I skipped over a slide. So this one slide
will show you how you– how easy it is to actually
cut out that code. So all you have to do is–
in this case, in my application, I had a, uh,
a “Show Images” dialogue button, and all I had to do
was guard that with a GWT.runAsync
and give it a callback. And then the compiler knows
that it can see all these split points,
split ’em out, and you get separate JavaScript that it can go off
and fetch later on. And it’s all magically
happening under the hood. You don’t have to think
about it. Ramsdale: So if we look at it,
it’s pretty staggering, though, the–the–the difference
in timing, so… when you have a non– this–so this is the amount
of time it’s spent waiting. Um, if you have
a non-bundled application, you end up spending,
you know, 1.4 seconds or 1,400 milliseconds waiting for the request
to actually initiate, go, and then you start getting data. When you bundle it, you drop
that down to 594 milliseconds, but you actually are doing– you’re incurring all of that
on the startup. So the blue is startup, and the green is actually
when you click the button. So you incur all of that latency
on startup. But when you bundle
and code-split, right, you get the best of both worlds. Uh, you have very minimal–
you have the– you have minimal startup time, and then you have
all of your bundling and all of your time spent
when you click the button. So it makes a big difference. Then finally, I mentioned– So now that we’ve–
we’ve gone through, and we’ve made it,
uh, optimized, and we’ve said, Okay, this is
how we can bundle the code. This is how we can defer it. What we’ve done is we’ve said,
Okay, there’s a– there’s a set amount
of JavaScript code that I have to use, and I’m gonna move it around
to when I actually need it. But let’s see how we can,
uh, basically minimize the amount of overall JavaScript
that my application uses in the first place. Uh, and this is nothing
that you have to do. This just happens for you
magically when you use GWT. But this is the–
the task application that I’ve been showing you. And what I’ve done is
I’ve run it through the compiler using prettyprint, and so it’s basically
what it would look like if you did
handwritten JavaScript. And you end up with a code size
of roughly about, uh, your initial fragment
is about a meg– 1.1 megs. When you turn on
the typical optimizations that the GWT Compiler gives you, you’re then hovering
around 400 and change in terms of overall output size, so it’s a pretty significant
difference. You’ve cut it by more than 50%. And so again, the less
JavaScript that you have, the less parse time,
the less drain on the battery, the better user experience. So now that we’ve talked about how to build great UIs
for any form factor, we’ve talked about how
to optimize the user experience, we’ve talked about
how to make it snappier and actually make it run like an installable
mobile application, let’s talk about how you can
work without a connection. ‘Cause again, like I said, these devices are meant
to be used on the go. They’re meant to be used
anywhere I want to. And the fact that it’s easy
to pull out of my pocket and use means that I’m more apt
to use it than, say, my laptop. So the problems
that were faced there are that you want to run
wherever, whenever, right? You want to basically launch
your application, and have it bring up something, some user interface
for you to use. For that, we can use
Application Cache to load resources locally. Then once you have
your application loaded, you want to be able
to use it, right? You need to interact with data. You need to be able to access
data wherever, whenever. And for that, we can use
Local Storage to attach RPCs. Ramsdale: So a little background
on Application Cache– Uh, it’s part of the HTML5
feature set. It works with files like HTML,
CSS, and JavaScript. You can load those from disk. It works with iPhone
and Android. And then it also works for
Chrome, Safari, and Firefox. And to make this work
with your GWT application, there’s a few things
you have to do. You end up declaring
an appcache.nocache.manifest, right? This is just a file
that you create. And then you go through,
and you list all of the permutations
that you have. You can leave out
all the RPC-generated ones. And the fact that you create–
you know, you call it “nocache” means that it will
always go fetch it. Then you go change
your web.xml file, and you actually add
this manifest file, and you actually add
the MIME type for it. And then you go through
and you update your HTML file to include this manifest file,
yada yada yada yada. Or you can just go check out
the 2.4 SDK… [laughs] where we–where we
started to make changes. Now it’s in beta mode,
and it’s– we’re having to split it out,
and it’s a little experimental. But, um, the idea is that,
you know, we know all of the files that
are part of your application. Well, let’s be honest,
we know almost all of them. So we know all the permutations. We know
all the JavaScript files. We know the CSS files
that you’re using. If you’re doing resource
bundling like I just mentioned, we know all of those files,
as well. And so, uh, we have this process when you go through,
and you compile, and you have
all these artifacts. At the end we say, Okay,
pull it all together, right? We call that linking, very much like
a normal compiler does, part of the normal
compiler process. So what you can do is say, Okay,
well, typically when I link, I just spit out
an HTML file, right? I spit out
the special nocache.js, and then I have my permutations. What you can do is you can
specify a new App Cache linker. Um, and in this case, you would say, Okay…
[clears throat] Mr. GWT Compiler,
when you go and run, and when you’re ready to link,
don’t use your standard linker. Use the one I’m–
I’m suggesting here. Uh, and it’s
an App Cache linker, and here’s the path to it. And it knows how to handle
everything for you. And then you can say,
Okay, by the way, now that I’ve defined this,
use it in my application. And this code goes into your
CloudTask.gwt.xml, your– basically your GWT application
configuration file that I mentioned before. And then, uh, the reason
that it’s specific to your app right now–
we’re working through this– is that it knows that, Okay, these are the set of files
that I compiled. Do you have anything else
that you want to add to the– the caching?
If so, just let me know. And then you take care
of it from there. So it ends up being
about four lines of code instead of all of that stuff
that I mentioned in the previous slide. So at that point in time,
you can load your application from disk, even if you
don’t have a connection. It pops up, not to mention
it’s caching most of the files that you don’t want
to fetch anyway, so your application just becomes
snappier to begin with, because it’s–
again, it’s saying, all– all the browser does is says,
Okay, I have a manifest file. Go off and grab it.
Has it changed? No, it hasn’t changed.
Great. I have all the resources
that I need on disk. Load those up– Much faster than doing
an RPC back and forth. Okay, so now that I can
load my application, I want to be able
to read data from it and work with it.
So how do I do that? [clears throat]
So we can use local storage to–to, uh, to make that happen. And again, much like App Cache, it’s part of the HTML5
feature set. Uh, if you don’t know, it’s a–
it’s a local database for reading and writing data. It’s very simple, just a key value
for your persistence. Um, again, it works
on iPhone, Android, and then Chrome, Safari,
and Firefox. Uh, and this is
already included. This shipped
with the GWT 2.3 SDK. So the way that we would
go about using this… [clears throat]
is in your application– anywhere you want to
in your application, you simply need to get in
an instance of the storage class. So you say “Storage.
getLocalStorageIfSupported.” And if you end up–
and this is, uh, the “IfSupported” part
is a way of doing a run-time check. So if you’re running
on Chrome or Safari, You’ll get back local storage. If you’re running
on IE6, 7, or 8, you won’t. And then you can fork
your application from there and make the necessary changes, like maybe you just choose
not to do local storage. Like on IE6, you just happen
to always fetch data over the wire, so that’s it.
They get a degraded performance. We want them to move
to IE9 anyway, so that’s okay. Um, so let’s say
that we actually do get the local storage class back.
We have an instance of it. We can start doing
some really cool stuff with it. One way you might use it, and the way that we use it
in this–this application is– well, okay, so your application,
somewhere in the code, says, uh, Hey, I need tasks. So you have a method
called getTasks, and what that would normally do
in–in a fully connected world, it would say, Oh,
just fire off an RPC, and when I get the tasks back,
I’ll update the application. Um, and in this new kind
of potentially offline world where we have local storage, what we’ll do is we’ll–
in the method, we’ll first say, Okay, well, let me grab them
from local storage. So let’s say
I get back a string. Great. That’s a string that’s
representing my task list. Now I need to deserialize it.
So now I have a list of tasks. That’s great.
These are the cached ones. And then I’ll fire off
an async request. This is where the async nature
of the browser really helps out. You automatically fire off
an async request, and you return,
pass that task– that list of tasks back
to your application. It’s none the wiser,
shows them, displays them. The RPC goes off. If it succeeds,
that’s fantastic. It comes back,
and when it comes back, you say, Okay, well, I’ve been
waiting for that data. That’s–I’m glad you–I’m glad
you could get it for me. Let me go ahead
and serialize it, get it into the string format. Let me persist it,
so that my cache is up to date for the next time I fetch it, and then you’ll do
whatever you need to do in your application, right? So you might pass an event
on the event bus, saying, like, Hey,
if you’re listening for, uh, task updates,
I’ve got one for you. Update the UI accordingly
and go on from there. And so now we’ve–
we’ve managed to go through and add the offline
support we needed to the application. We’re kind of bringing it
all together. And what we’ll do
to prove it out… is flip this off. And see, the nice thing is if the Wi-Fi completely
went down in this demo, since it works offline–
I was good to go. But let’s force that
to happen anyways. Ramsdale: Great.
So we have the application we’ve been using all along up. Let’s go ahead and add an, uh, icon to the home screen to give us the full effect. So “Add shortcut to home.” Over here, let’s see… “Bookmarks,” “Shortcut to home.” All right. So note that we’re connected. Let’s go ahead and kill that. Now you can read my e-mail. [chuckles] [clears throat]
All right. So that’s on. I have no connection. Ramsdale: All right.
Airplane mode for both. Ramsdale: Come back. Now there’s a slight glitch
that you’ll have to deal with. This is a weird browser quirk
we haven’t got around. Okay, so the first time I do it, it says, uh, I-I–
it realizes that it’s offline and just throws up the default.
Uh, I can’t connect. But then what you see is that
my application is connected. If I keep hitting “refresh”
while I’m in airplane mode, I get it. I can actually see my task list. Right? I get back support. Ramsdale: Do the same thing
over here– I can go through,
and I can see. Click. Back support. Ramsdale: All right, and now,
see, I go away and leave my application. And then I’m–I’m driving
through the subway. I want to–I’m in the middle
of Kansas again. I’m on the plane.
I can just click on my icon. I’ve got my application here. I can select it. I can see all my data. We can go check out the,
you know, Blue Bottle coffee shop because I hear
they have great espresso. Same thing works on my phone. All my data’s here. I can click on it,
and I can see it. So fully functioning
mobile web app. Now I’m not–I’m not connected
to the cloud at all. I have everything in my browser,
and it’s actually operating like a real, true… installable application. Ramsdale: [clears throat] [applause]
Ramsdale: Oh, thanks. Ramsdale: So we’ve gone
through a lot. We’ve gone through
saying, okay– we’ve identified
that we’re web developers. We know we want to do mobile.
It’s the new hotness. Uh, we’d love to reuse our code.
We know there’s friction. We’ve gone through
what those problems are. Um, and we’ve identified
that, you know, what you want to do is–
it’s tough. You have to make UIs
that work on every device, so you need tools and frameworks
to make that easy to do, and that’s what GWT provides– UiBinder and GWT Designer. Um, you need, uh, to optimize
for the user experience, right? You need to be able
to pick that UI very easily. And you need to have it happen
without you having to write, you know,
thousands of lines of code. You can do that
with deferred properties and actually using
built-in GWT features. And then finally,
you need to optimize for the user experience, right? You need to make it as small
as possible. So we can–we’ve shown
how we can bundle resources, how we can move them around
your application to when you
absolutely need them. And then we can ultimately,
using the compiler, right, to do obfuscation,
dead code analysis, method folding– you can actually reduce
the overall size of your JavaScript
by sometimes 50%, right? And then finally, we need–
we need APIs, good, easy-to-use APIs
for working offline. And we’ve demonstrated that
using App cache, GWT linkers,
and local storage support. So with these all in hand,
I hope that, uh, you can actually now go back
and look at your web app code and say, “This is great.” I’ve got, you know,
30,000 lines of code, and there’s a good chance
that I can go reuse 20,000 of them
or 25,000 or however many it may be and easily get yourself
a mobile web app that actually runs
and can work offline and can work and have
a great user experience. So thanks. And so, uh, all of the code
that I mentioned is available now, um,
on our main code site. So you can just go download the 2.4 beta version
of our SDK, and you’ll see this application
as well as the linker. And then other sessions that you
might want to check out. So the page speed guys
that helped me out with the graphs for what it
looks like on a mobile device, um–they gave a talk yesterday. So go–be sure to go back
and check out the YouTube link that we’ll post
on our main site. And then, uh,
there’s some great sessions that are happening today. So you have “Mobile Web App– Mobile Web Development:
From Zero to Hero.” That’s given by some
of the Chrome guys. That’s at 12:30 today. Uh, and then a fantastic–and I
actually saw this rehearsed– A fantastic, uh, debate between the Chrome
and the Android guys called “HTML5 versus Android: Apps for Mobile
Web App Development.” There’s actually a fight
at the end. No, I’m just kidding. [laughs]
[laughter] Ramsdale: So, uh, that’s it.
Thanks for joining. And I’ve got now around
ten minutes to take Q&A. [applause] man: What about–is it working?
Ramsdale: Yep. man: What about
hardware acceleration– hardware acceleration
with GWT? And does GWT work with canvas, with HTML5 canvas? Ramsdale: Uh, yes. So GWT
does work with HTML5 canvas. It was one of the first APIs
that we, uh, that we started supporting. So the list is canvas,
audio and video, local storage, and now
the beginnings of App Cache. And then the first–
the first part of your question was, Does it work
with hardware acceleration? Like, so are you talking about,
Do we have APIs for WebGL? man: Yes, that’s right.
Ramsdale: Uh, not yet. We’ve, uh, there’s some
game development going on in some talks today,
so I would suggest, like, the “Kickass Game Programming
with, uh”– excuse me–“with GWT”– later on today–
that you should go check out, and they’re starting
to talk about that. man: Okay, just one last–
uh, how do I write JavaScript code on the Java–
on the GWT– for example,
uh, JQuery and those? Ramsdale: Well,
if you’re looking for– if you’re interested in JQuery, I would suggest you look
at GwtQuery. It’s kind of, uh, it’s the– it’s the parallel effort
in the GWT world. And then if you just want
to bump down and have handwritten JavaScript, I suggest you go back and look
at our–our main code site or just use our search engine
for looking up, uh, JSNI. So that’s JavaScript
Native Interface, and it’ll show you how to jump
from Java into native JavaScript. man: Okay, thank you.
Ramsdale: Yep. man: Yeah, I have a question
on, uh, scrolling. Could you talk a little bit about how we can handle
scrolling easily, uh, and detach–
and handling detached events? We have a system that we built
using GWT. And, uh, when you try
to use it on, uh, on an iPad, you know, it–it kind of was pretty
difficult to implement that. It had to detect
detached events, and the scrolling
was pretty bad. So–so is there any way–
like, can we just say, [speaking indistinctly] and then magically have it,
uh, scroll with a finger– a single finger? Ramsdale: Were you
using the, uh, so there’s a new panel called, uh, touch panel
that implements that. Were you using the touch panel
to do that? I mean, was it recently? man: Uh, no, we didn’t–
we did not use the touch panel. Ramsdale: Okay, so, um– and–and so what I was
showing you here was based on a panel
called touch panel that’s part of the 2.4 beta SDK. Um, and while there still is
a tad bit– I’ll be honest with you– There’s still a tad bit
of flickering on the tablet. On the, uh, mobile device,
it’s very, very clean. So I-I’d suggest trying it out
on–on an iPad, ’cause I think that you’ll see
some–some better performance. man: Okay, thanks.
Ramsdale: Yep. man: Um, I’ve got
a couple questions. But I guess, um, first,
is there just a good way to test GWT code
in a global browser? ‘Cause obviously, you can’t
do development mode in there, and so the constant recompile
is sometimes annoying. Um, and then my other question
is, if I use– I mean, I’ve tried taking
some of the MVP design projects that we have using–
and they use GIN a lot. And the problem is sometimes
the deferred binding– or the–the configuration
that you would put in your module XML, uh, it’s hard to say
if the form factor is tablet, then do a generator for this GIN thing. Do the–so generate
the tablet Ginjector or the desktop Ginjector
or the mobile Ginjector. I mean, so some of the– it seems like there’s
a couple of– and GIN actually, I recall,
has an extend– you can extend
the configuration and introduce modules through– through the module XML,
as well, but it also doesn’t always
like that of saying if this is a thing,
then extend this and add this special module– uh, desktop module
or mobile module, um… Ramsdale: So is your–
is your general question, How do you use deferred bindings
with GWT–with GIN? man: [clears throat]
Ramsdale: Easily? man: Yeah, sure.
Ramsdale: Yeah. man: [laughs]
Ramsdale: Um, so I’m– I’m not the expert on GIN. Um, I think there’s one
in the audience that I can defer to
a little later. But why don’t you
catch us afterwards, and if not, we’ll–we can
exchange some e-mails… man: Okay.
Ramsdale: To get an answer on if it’s possible or if it actually is
a very hairy route to go down. man: Okay.
Ramsdale: Yep, thanks. man: Hey, um, I haven’t
used App Cache yet, so this isn’t really
from personal experience. But from what I’ve read,
there have been a lot of, like, refresh issues, that browsers aren’t actually
looking for new manifests and aren’t gonna download
new resources. Um, have you noticed that? Does GWT do anything
to address that? Ramsdale: Um, you know, I’m–
I’ll speak from, uh, these are some hot bits
that–that I’m try– man: Yeah.
Ramsdale: I’m testing out, so we’ve only really
tried it out on, uh, Android tablets
and Android phones. So far, we haven’t had
any problems. Um, and I mean,
so, uh, optimistically, I think that it’s gonna
work perfectly fine on, uh, iPhones and iPads, because they’re both built
from the web kit base. And where they deviate, they don’t deviate
at the part of the code that actually goes and fetches
the, like, App Cache manifest. So, um, so to answer
your question, uh, we haven’t seen any problems
on Android devices. And I don’t believe
we’re gonna find any problems on iPhone or iPad,
but I do know that, um, there’s inevitably a very strong
push for HTML5 amongst those two browsers
and including Firefox. So I’m–any issues that we see,
I expect to be resolved. man: Okay, good enough. Thanks.
Ramsdale: Yep. man: Hi. Uh, is Xoom
in the offline mode– your application was read-only?
Like, you cannot add tasks? Ramsdale: Right.
man: So I was, uh, thinking if there’s, uh,
any support in the works or any ideas about, uh,
you know, synching, um, any modifications
to the data? Ramsdale: Uh, so we’ve talked
extensively about this, and, um, in fact, we just
talked about it yesterday. We, uh, it would be
a great engineering problem to go solve. We have various ways
that we could do it, but, um, myself and Ray,
who’s sitting right here, have–we’ve basically landed on
that right now, at least, it’s best to leave that up
to the application developer, although it might be
a little bit tricky. Um, and–and–because
how you want to queue and how you want to be
aggressive with fetching or not aggressive–
you want a read-through cache or write-through cache,
you know, whatever– that–that’s kind of left up
to the application developer. The one thing that I didn’t show
that would be interesting is the ability to take–
like, I omitted the de–the serialization
and deserialization code there. But if you’re using things like,
uh, RequestFactory, it becomes very easy to just–
there–all that code is already existing there. And so we could make it
easier for you via APIs to say, Here’s my–
here’s my object graph. Can you just give me back
a string, right? And we could give it
back to you, and then you could store
that away, right, and go from there. So the answer is that we’re
not gonna tackle, um, queuing of reads and writes
for you yet, but we can provide APIs
that make it easier. That’s–that’s on
the short-term road map. man: Are there any examples
out there? Ramsdale: For… man: For this kind of operation? Ramsdale: Um, I-I– none that come off
from the top of mind. I-I would say just do
a quick search for– for it out there
and see what you can find. man: Okay.
Ramsdale: Or, you know, there’s 26,000 members
on the GWT user group now. I would try maybe to ping them
and see if there’s, uh, anybody that’s given it a shot.
man: Okay, thank you. Ramsdale: Yeah. man: Hi. I think you
partially answered this, uh, on the previous question, but, um, with offline support– so I’ve tried without GWT,
just a plain HTML page– I’ve tried to do that, uh,
with the iPhone browser. And I got error messages
similar to the one that you just, uh, ran into, where it–it presented
an error message. And then I think
it continued to work after I dismissed the error,
but that almost feels like a showstopper to me
in terms of, um, deploying something
that I expect end users, you know, nontechnical users
to use. Uh, what else can you–
do you know about that error? It sounds like you haven’t tried
it on iPhone yet, I guess. Uh, I don’t know. Do you
know anything else about– about what’s causing that,
or when it… Ramsdale: Uh, no,
at this time, I don’t. man: Okay.
Ramsdale: I mean, we’ll continue to look into it, because if I–
if I pop it up– well, if you want to see it,
I… [clears throat] there’s another part of the demo
where you would show actually loading a page,
and the page– like, so for, that does not have
App Cache in it– it literally would not
load up at all. So yes, I think that it’s, uh,
I-I think it’s a defect, and that’s a browser one,
I believe. But, um, you know, we’ll have
to work through that, and–and make it better
and get rid of that– that pop-up that you saw. And if there’s something that we
can do in our–in the way that we’re constructing
our App Cache manifest file to get around it, yeah,
we’ll keep digging and find out. And then obviously, we’ll make
that part of the linker that we’re exposing.
man: Yep, okay. Thanks. man: Yeah, hi.
Um, I was wondering, uh, you talked about
resource bundling and form factor. Um, is there a plan
to support, uh, different network latencies or network congestion issues, so that I can have one UI for a low latency and another UI
for high latency in my applications? Ramsdale: Yeah, are you talking
about low latency versus high latency? man: Yeah, so that I can have
low-resolution images and, uh, a sort of
leaner application for hard cases. Ramsdale: Well, this might be
a little bit crazy, but, um, I-I don’t think
that you would– you couldn’t attack that from
a deferred binding standpoint, at least not off the top
of my head. Um, what you’d end up doing is
something a little more custom where you would, you know,
you would be doing– you could do timing
of your RPCs. And if you happen to notice that it’s taking
over some threshold… man: Mm-hmm.
Ramsdale: You can kick your application
into a different mode. man: So I can hack it, but it’s
not supported and built-in? Ramsdale: Well,
it’s not that it’s not– it’s just not supported via
deferred binding. Like, deferred binding
is something that we make, uh, like, at the point
of request, right? We’re deciding, um, we–we decide which–
which permutation to offer up. man: Mm-hmm.
Ramsdale: You could do a– you could potentially do
a custom one, where you do a–you could do
a check beforehand, um, and then you get
some timing. And then if it’s based
on a threshold, you could pass
that property along and do your own custom
deferred binding. But at that point in time,
I think that you’re using the– I think you’re actually using
the feature incorrectly. And it might actually be
more code for you to write, rather than if you just picked
up on the fact that, Okay, my application
just switched into a very,
very high-latency mode. So I’m gonna tell–
I’m gonna–I’m gonna have a way to–the way I forked
for different devices. man: Mm-hmm. Ramsdale: You could do that
customly and– Actually, the way that I forked
for the orientation change, I didn’t actually do that
via deferred binding. I did that
as a run-time check, right? And you could do the same thing,
and you could say, Okay, the–all those UiBinder
template files, forget those, because those are
very graphic-intensive. Let’s go with my very, you know,
vanilla page over here until I–and then you have
in the background a thread that keeps waking up.
man: Mm-hmm. Ramsdale: I call it a thread,
but you just have some async code that’s running that keeps checking
for the timing of RPCs, and when you see that you’re
in a high-latency– a low-latency area,
do the switch again. man: I see. Ramsdale: That would be
my suggestion. man: Okay, thank you.
Ramsdale: Yep. woman: Go ahead.
man: Hey. I’ve got a question
for the offline manifest. I was wondering if it was
optimized for each browser. So–so if I’m in IE,
do I download only the five
that I need for IE? And if I am Firefox
or on iPhone… Ramsdale: [sighs]
That’s a good point. We’ll have to go back
and look at that. The–the… Ramsdale: There is something
that’s a bit of a deficiency with App Cache
when you use it this way. Let me explain it,
and hear me out on the entire portion of it. With App Cache, um, right now,
at least the way we have it, and the way I demo’ed it,
you’re pulling down all the permutations,
which is not optimal, right? But what you get in return– so it actually becomes
like an installable experience. Imagine that if you’re–
you’re downloading an application from
the Android Marketplace, you’re kind of fine
with the fact that it takes five seconds
or ten seconds, or even if it takes a minute
to download, right? ‘Cause it’s downloading
everything you need. So when you switch
to the App Cache mode, at least the way I demo’ed it, you’re doing
the exact same thing. You’re saying
I want this application, and you get all the files
associated with it. So right now,
it’s not totally optimal, because you get all
those other permutations. We can work on that.
Um, but then once you have them, Right? You’ve “installed”
the application, and now it just runs from disk,
so it’s much faster. So, uh, no,
not right off the bat, but I know that we’re
hooking into the– the compilation system,
and so there might be a way to actually split out
and say, Okay, compiler, you’re asking me
for the App Cache manifest, and I’m–I’m–you’re asking
under these pretenses, which is Firefox or IE
or Chrome. man: Thank you.
Ramsdale: Yep. Ramsdale: All right, cool.


  1. Post
    Mohd Faisal Poat Kamal

    Great presentation.
    Anyone know where I can find the code example for this presentation?
    Can't find it in gwt page.

  2. Post
  3. Post
  4. Post
  5. Post
  6. Post
    sylwek wojciechowski

    why they cant talk about opera mobile. This browser is pretty fast and don't need the difrent mobile view,

  7. Post

    excellent presentation.
    I had the impression his face was familiar, then I recalled that he looks exactly like the Brother in law of the main actor from Breaking Bad ( the anti drugs police agent).

  8. Post
  9. Post
  10. Post

Leave a Reply

Your email address will not be published. Required fields are marked *