(music playing)
One of the dominant design principles that Android adheres to
is that it's a multi-tasking operating system.
Users can have multiple apps running and quickly swap between them as needed.
My name is Cole McAnlis, and to make sure that your app is performing well,
regardless of what the other apps are doing on the device,
it takes a bit of prep work and a few handy APIs.
At its core, this has everything to do with the tragedy of the commons.
Specifically, apps will act regarding their specific situation
without consideration for the larger environment.
Now by themselves, this isn't necessarily a big problem.
But remember that each running app is taking up a small piece
of the device's limited resources.
And when those overall resources run out, the user experience suffers.
Each running application has a set of resources
that are resident in the device's memory. For example, its state information,
graphics resources, and for the most part, all of its allocated heap objects
stick around in memory even when the application is in the background.
Over time, the device will, as expected, run out of available memory,
since it's being taken up by other apps, and will need to kill an existing app
in order to free up memory for the active application.
Remember that the whole reason we keep background application in memory
is so that switching to a background app between a foreground app
is a pretty fast process. But this doesn't apply for killed background apps.
If your app is killed and the user comes back to it,
we got to start from scratch, relaunching the app
as though it had never been loaded into memory in the first place,
which is a much slower operation than swapping to it from the background.
But the good news is that your app doesn't have to be killed.
Instead, when memory gets tight, your app can offer up some of its allocated space
back to the system, in order to avoid the pain of being terminated.
To facilitate this ritual sacrifice of memory transfer,
Android offers a set of callbacks that will be issued to your app
that you need to respond to. But first, let's talk about
what things happen when they go horribly wrong.
Once all of the other background applications
have been killed, in order to save memory,
the active application will get an on low memory callback,
which signals that things have gone horrible
and that it should immediately release any in memory resources
to help stabilize the system. If you have things in memory
that aren't needed right now, this is when you need to free them.
But sadly, this callback only happens
after all the background apps have been killed.
It would really be nice if instead of killing those background applications,
they were allowed to collectively release some memory back to the system,
which would help move everything along but also keep them from being killed off.
This is the exact reason why the on-trim memory callback
was provided with the release of Ice Cream Sandwich.
This callback is issued to all running applications
and gives them the ability to release memory rather than being killed.
This is facilitated by an integer value that's provided to the callback.
The trim level that's given to you is a value between 0 and 100.
But there are a handful of values defined, which you can check against.
For example the trim memory moderate value means the device is running low on memory.
And it's a great time for your app to start evicting things,
like your bitmap thumbnail cache, while the trim memory background flag
means that some background applications are starting to be killed
and that the app has recently transitioned to being a background app.
This is a great time to free up memory that won't be critical if the user
comes back to your app really quick.
Oh, and if you're comparing against these values,
you might want to make sure to use a greater than equal comparison,
just in case we add new defined values in the future.
And the best part is that in order to help you free up memory
from every corner of your app, this callback can be overridden
on activity, fragment, service, content provider, and application classes.
But in order to produce the best user experience,
your app shouldn't just be reactive to type memory situations,
but also proactive, depending on the device.
The ActivityManager.isLowRamDevice API that was added in KitKat
can be used to help detect if your application is running
on a device with low memory. Currently, a return value of true
typically indicates memory of 512 megabytes or less.
This condition should be used by apps
to help decide what features to enable or disable,
depending on whether or not it's going to be a good user experience
for these low memory devices.
Of course, playing nice with the rest of the system
is just the tip of the iceberg, which is why you need to check out
the rest of the Android Performance Patterns content.
Oh, and don't forget to join our Google+ community
for other great tips from other great developers.
So keep calm, profile your code, and always remember,
Perf Matters.
(music playing)