Intro To Android (Workbook 2)

Memory Analysis

Overview

Understanding how the Android system works at a low level can help you make better decisions when designing and implementing your application.

We'll review several key concepts from the excellent memory primer from Android's documentation: Managing Your App's Memory.

  • There's a constrained heap size for each app. When you run out, you get an OutOfMemoryError and Android doesn't defrag your heap.
  • If your app holds on to memory it doesn't need it will constrain overall performance, even when cached and in the background.
  • You should limit the use of services and properly handle stopping the service when you have one. They aren't usually killed, so they eat a lot of system memory.
  • Enums often require more than twice as much memory as static constants.
  • Every class in Java (including anonymous inner classes) uses about 500 bytes of code and every class instance has 12-16 bytes of RAM overhead.
  • Be careful or abstractions and object-heavy designs as the overhead for managing these objects come at a high cost.
  • Limit usage of libraries and dependency injection.

Micro Optimizations

Source: http://developer.android.com/training/articles/perf-tips.html

There are two basic rules for writing efficient code:

  • Don't do work that you don't need to do.
  • Don't allocate memory if you can avoid it.
  • Avoid creating unnecessary objects as "[o]bject creation is never free."
  • Use static whenever possible since "[i]nvocations will be about 15%-20% faster."
  • Avoid internal getters and setters because it is somewhere between 3x to 7x faster to access the field directly than to invoke a trivial getter.
  • Use the enhanced for loop as much as possible unless iterating an ArrayList.
  • Use protected for inner classes instead of private.
  • Use int over float where possible since it's 2x faster.

Avoiding memory leaks

"[Most] memory leaks [are] due to the same mistake: keeping a long-lived reference to a Context."

  • Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
  • Try using the context-application instead of a context-activity
  • Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance
  • A garbage collector is not an insurance against memory leaks.

Source: Avoiding Memory Leaks

WeakReferences

When we use strong (regular) references, we tell the garbage collector not to collect the memory associated with that variable. That means that we need to keep a close watch on the reference.

Enter WeakReferences. You can tell the garbage collector that you're fine with this reference being cleared up.

WeakReference<Activity> weakActivity;

weakActivity = new WeakReference<Activity>(activity);

Activity activity = weakActivity.get();
if (activity != null) {
    // ...
}

Further Exploration