I gave a talk at #OMRS15 on MSF’s efforts to make Project Buendia easy to customize and deploy, with a focus on nutrition programs. These are the slides (pdf, 4.5 MB). Speaker notes also available (pdf, < 1 MB).
I’ve been working on Android apps at Google for about two years. In that time I’ve worked on a diverse set of codebases - from small, tightly-contained internal tools that only target Lollipop and newer, to extremely complicated apps with large development teams, such as Google Maps, and even system-level code such as the Activity Manager for Android Auto. In that time, I’ve also seen a lot of new team members come up to speed, and found myself consistently giving the same advice to help them get there quickly. Here’s my top three tips for becoming productive whilst developing for Android.
Rule number 1 of writing code is that you’ll spend more time reading code than actually writing it. If you’re using Android Studio (it’s pretty good!), you can make this easier by learning how to navigate through code semantically. Basically, take a look at the Navigate menu and make yourself familiar with the options there. My most commonly used options:
This advice was something my manager gave me when I first started programming Android, and it’s been the single biggest thing that improved my productivity developing for the platform. You’ll find yourself using these a lot, so it’s worth remapping them to keystrokes that work for you as well.
Android’s frameworks aren’t always well-documented, but the most complete kind of documentation is source code, and the source code is available. Make sure you download the framework source as part of the Android SDK, and then when you use the code navigation features in Android Studio, you can jump right into the Android source and see what’s happening under the hood. You can install the Android source by checking the Sources box in the SDK manager. From the Android Studio menu, choose Tools –> SDK Manager –> Show Package Details, and then check the Sources option:
The ‘SDK Manager’ window.
Android lifecycle is one of the most confusing paradigms I’ve ever worked with in programming. Unfortunately, it’s also crucial to the platform, so it’s important to make sure you understand it well so you don’t introduce subtle bugs.
As an example, I’ve seen lots of code that resumes and pauses rendering in
onPause() respectively. These callbacks don’t indicate visibility, though, they indicate that the Activity is in the foreground, and that the user can interact with the app. This results in a problem where rendering stops when a dialog pops up over the top, for example. Instead, rendering should be started and stopped in
onStop(), respectively, which indicate when the Activity is visible at all.
The best guide to Android lifecycle is in the Android documentation for the
Hopefully these three tips will help you to get up and running quicker with Android development! Let me know if you’ve got any other advice that really helped you to get started.
For the Buendia medical records system project, we’re building an Android tablet app that’s capable of displaying and modifying electronic records out in the field. So far, we’ve been targeting the Sony Xperia Z2 tablets as our reference platform - they’re a great size, they’re really light and they’re waterproof.
The project is open-source, and we’re finding that we have contributors who want to help, but don’t have a tablet device to test on. We’ve had developers use the Android emulator before, but emulation can be quite resource-intensive. Even if you’ve enabled HAXM (it’s a huge speed-up if your processor supports it!), the emulator still uses a couple of GB of RAM, which, in combination with Android Studio, can push even modern hardware pretty hard!
Whilst not everyone has an Android tablet, lots of our developers have Android phones, and want to use them for running the app, even though we’re not planning on supporting phones currently. It turns out you can tell Android’s Window Manager to use whatever resolution you want, and using this, we’re able to help developers be just a little more productive without the Android tablet.
Here’s how to do it:
A few notes:
1200x1920depending on the default orientation of your device.
These settings will persist until you reset them manually, so make sure to run this when you’re done and want your phone back to normal:
That’s it! Feel free to drop me a note and let me know if this works on your device.
Lots of developers love the
Application class as a container for application-wide resources, because:
Context(in fact, it is a
This, however, is actually a really bad idea that will only cause you pain, for two main reasons:
Applicationtoo much scope, which makes your code harder to maintain.
I’m going to explain these reasons in detail, but first, I’ll show you how not to do app-level state, using an example app that I just made up. It’s called PictoBlaster, because it allows you to apply filters to pictures and then ‘blast’ them to your friends1.
It’s really easy to go down the route of putting resources in your
Application class (again, please don’t do this):
BadAppclass that inherits from the
AndroidManifest.xml, add the
android:nameattribute to your
application(in the same way that you would for an
Seriously, don’t do this.
Developers often forget that
BadApp is loaded into memory when Android initializes your process, and before any other component can be loaded. That’s not a big problem for apps that only have a single Activity, but as soon as you start adding other components (other Activities, Services, BroadcastReceivers, or ContentProviders),
BadApp has to load all its dependencies before any of those can be started. This is especially true for components that are supposed to be lightweight, such as BroadcastReceivers and ContentProviders.
Loading those resources burdens the operating system unnecessarily. Consider the following scenario:
So far, so good. The problem occurs when the PictoBlaster process has to be loaded again for what should be a lightweight component:
BadAppclass loads all of its resources into memory – Filters, Cheesy memory-intensive stickers, Fonts, everything.
BadApphas finished initializing, the
BroadcastReceivernotices that the phone has reconnected, reads the file from disk, sends it over the network, and exits.
Not only is this a waste of the users’ battery (how long did it take to initialize all that stuff?), if BadApp initializes enough stuff, it can also create memory pressure that causes other apps to be shut down3. This is especially true if the user’s loaded another memory-intensive app in the meantime.
The root problem here is that resources are loaded eagerly on process start, whether they’re going to get used or not. This is almost never something you want. In a resource-constrained mobile environment, it wastes battery and memory, which can kill other apps that the user may be interacting with. That’s a terrible user experience.
It is possible to work around this by making all of your Application-level resources lazy-loaded using an explicit lazy initialization mechanism, such as Guava’s
Suppliers.memoize() or Apache Commons’
LazyInitializer. This workaround still doesn’t solve the maintainability problem, though.
The other major problem with initializing all your resources in your
Application is that it makes it easy to give your
Application too much scope. Once there’s a precedent for putting app-wide resources in your
Application class, other developers on your team will put them there too. Then, you’ve got a class that owns loads of different resources.4
A side effect of giving your
Application too much scope is that if you ever want to reuse code that uses these dependencies, pulling the code out into a separate library isn’t a simple task - you’ve got to decouple your app-wide resources from the
Application object first.
I think that the real reason why a lot of developers like the
Application class so much is that programmers have often been taught that static members are evil. Actually, static members are extremely useful whenever you’re working with resources that are scoped to a process (the app, in this case). The
Application class represents exactly the same concept, it just allows developers to avoid the icky feeling they get from using static members instead.
Java’s semantics for static members are pretty useful. Static members are initialized when the class is loaded, which means that they’re loaded the first time you use a static member or instantiate the class. This gives you lazy-loading for free, without having to write boilerplate yourself. The ‘static instance’ approach is one that Android framework engineers have recommended in the past.
The idea is to define a class like this:
…and then reference
AppWideResource.INSTANCE whenever you need one.
There are a couple of disadvantages to this approach:
Context. The Android documentation for Application hints at a solution like this:
Likewise, if you need other static resources to initialize your
AppWideResource, just add them as parameters to the
The structure of this approach means that:
Our metrics look like hockey sticks and we just closed a Series A for $20m, probably. Our logo is the pair of emoji 📷🚀. ↩
An alternative to the
BadApp#getInstance() method is to use
(BadApp) context.getApplicationContext(). This isn’t any better. ↩
A really good indication that an object has too much scope is when you find yourself mocking things out in tests that seem completely unrelated. If you find yourself doing this, it might be time to rethink your design. ↩
This website has always been about having an identity on the internet. It was a vogue thing in the 2000s, I think. If you were SRS BSNS about the internet, you had your own domain name. And for some reason I took that and ran with it a few years late in 2011.
I maintain that personal websites occupy a unique space on the internet - it’s pretty much the only place where what you write isn’t massaged into a format for others to consume.
No seriously, let me unpack this a little. There’s two main axes that you can put categorize pretty much every social network into:
Personal websites are unique in that they can be whatever you want them to be, and as such they have a high level of user control over their representation. As a side-effect of this, it’s also easier to build something that tells a coherent story over a longer time-frame. Compare this to a few common social networks:
On Facebook, The Feed is the core element, your identity on the service is almost entirely what you post to and what you interact with on The Feed. Virtually everything you interact with could be shown to your friends, even if it’s just clicking the little 👍 button. The profile exists only so that other users can ascertain who you are before adding you, and so that Facebook can target its ads better. You’ll notice that Facebook has reduced the role of the profile over the years as well - indicating “interests” was an important part of profile-building in the beginning, but that’s probably a hangup from being a competitor with MySpace a long time ago (You were not my friend, Tom). I’d argue that a notion of a profile is important for long-term story-telling, but Facebook are exploring more novel approaches in this area in the name of engagement.
On Twitter, you’ve got the same core model, but the content is shallower, and you’ve got more control over what your followers see - everything that goes in your stream is there from a deliberate action, and if you ✭ something, that ✭ won’t be broadcast to all your friends (there were contentious attempts to change this recently). It’s even harder to tell a cohesive story over the long term on Twitter than it is on Facebook, because:
Instagram is an interesting one - the uniformity and non-text nature of the medium makes it easier to look back at old posts. It’s easier to tell a cohesive story over the long-term on Instagram, probably because Instagram profiles are reminiscent of photo albums. This isn’t the case for everyone, but I’ve certainly flicked back through my Instagram profile to find a photo for something that I was telling a friend about before. I’d wager it’s also because the content is first-user-generated - there’s no reshares on Instagram, so every single thing you post is something that you probably directly experienced.
I put together Version 1 of this website whilst sitting in Engineering Management lectures at university, and it was
<marquee>animations</marquee>, and the whole thing was powered by PHP and MySQL. I also had the insight that not everyone would be interested in all the different stuff that I was writing about, so I had this thing where you could filter categories, and the posts were all colour-coded. I was scratching at the idea of online identity, though, so I didn’t want to fork content into separate sites just because people might not be interested in all of it.
Wow. At least it’s different, I guess?
Gosh Darn. What was I thinking? I think the laptop I was using then had terrible colour saturation. Also, I had to install Apache/PHP/MySQL and turn off a bunch of Deprecated MySQL-non-prepared-statement-API warnings to generate that screenshot. It brought back some bad memories (this is a good setup guide though).
Version 2 was the same content, but converted to use Octopress 2, because the other site was kinda unusable, ugly and extremely difficult to maintain. It was also slow because it was stored in a MySQL database on a single server located in Melbourne, Australia (I think). It might’ve had a condition where the page rendering performance degraded the more articles you tried to load, too.
Anyway, now that I was using an entirely static site, I could move the whole thing over to Github pages, because I liked the idea of being hosted on a performant, worldwide CDN. This was mostly because of a desire to not be fireballed, because I had big hopes that something I wrote would one day be read by lots of people (lol). There was still a big focus on blogging and on content.
Not as much personality; this was pretty close to the stock Octopress template.
The Octopress blog was ok, but I found over the next few years whilst working full-time in a fairly demanding job that I didn’t really have time or energy to write. I found that I was returning to the idea of a domain as “an identity on the internet”, and was more interested in having a place to centralise content I’d produced elsewhere - on social media, particularly. So I started experimenting again late in 2014, and then rebuilt the site to the format you see today over the six months or so following.
Conceptually, what differs in this iteration compared to the last two is that it’s designed to stay relevant for minimal effort. I’ve done this by:
Design-wise, I’ve updated for a bunch of newer web paradigms. So, it’s responsive (go ahead, take a look on your phone!), space / cache-efficient, and super clean. Drop shadows are subtle. There are no peeling stickers. Remember when that was a thing? That was the worst.
Update (Jul 2016): As time went on, I found that the commentary I was writing was pretty important for interpretation of the work. This was particularly true for Embassy Reviews and Emoji Haikus, both of which are a little more abstract than content I’ve historically produced. To reflect the fact that I thought this commentary was important, and easy to miss with this design, I inverted the paradigm so that a ➤ (
BLACK RIGHTWARDS ARROWHEAD) provides a direct link to the content, and the title is a link to the commentary. ↩
|← Older||Index||Newer →|