Android Performance Tips

by Samm Bennett

While getting ready to write a new Android app, I decided to see if there might be any neat tips and tricks in the Best Practices section on the Android developer site. Boy was I not disappointed! I've only reviewed 2 sections so far, those on Performance and Memory Management, but I'm eager to tackle the rest. The following are some choice tidbits from each.

Note that these tips are specific to Android, and might not be ideal in other environments (due to differences in the JVM or platform considerations).

Performance Tips

Prefer static over virtual methods

If you don't need to access an object's fields, make your method static. Invocations will be about 15%-20% faster.

Use static final for constants

The optimization itself applies only to primitives and Strings, although it's generally best practice to make constants as such.

Getters / setters

Without a JIT, direct field access is about 3x faster than invoking a trivial getter. With the JIT (where direct field access is as cheap as accessing a local), direct field access is about 7x faster than invoking a trivial getter. Note that if you're using ProGuard, you can have the best of both worlds because ProGuard can inline accessors for you.

For loops

This one really surprised me:

With an ArrayList, a hand-written counted loop is about 3x faster (with or without JIT), but for other collections the enhanced for loop syntax will be exactly equivalent to explicit iterator usage.

In the following code, "the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop":

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;

Be mindful of private access with private inner classes

To summarize, when a private inner class tries to access the private member variables of the containing class, the compiler generates some synthetic, static methods to wrap member access. This is because, while legal, the VM considers one class assessing another class' private members to be illegal. As mentioned earlier, using a getter / setter can be 3x - 7x slower than direct member access.

Managing Memory

Release memory when your user interface is hidden

To be notified when the user exits your UI, implement the onTrimMemory() callback in your Activity classes. You should use this method to listen for the TRIM_MEMORY_UI_HIDDEN level, which indicates your UI is now hidden from view and you should free resources that only your UI uses.

Notice that your app receives the onTrimMemory() callback with TRIM_MEMORY_UI_HIDDEN only when all the UI components of your app process become hidden from the user. This is distinct from the onStop() callback, which is called when an Activity instance becomes hidden, which occurs even when the user moves to another activity in your app.

Use optimized data containers

Take advantage of optimized containers in the Android framework, such as SparseArray, SparseBooleanArray, and LongSparseArray.

Be aware of memory overhead

Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android. Every class in Java (including anonymous inner classes) uses about 500 bytes of code. Every class instance has 12-16 bytes of RAM overhead.