Activities are Not Destroyed to Free Up Heap Space

If you’re like me, when you read passages in the SDK documentation like:

If an activity is paused or stopped, the system can drop it from memory… by asking it to finish (calling its finish() method)

and:

(onDestroy() is called) because the system is temporarily destroying this instance of the activity to save space

you might think that Android will destroy activities to free up heap space. I envisioned Android checking free heap space from time to time, and when it fell below some threshold, it would destroy an activity that had been pushed into the background, thereby freeing up its heap space.

Apparently, that is not the case. And, to the extent that I steered you wrong on this point previously, please accept my sincere apologies.

In a recent StackOverflow answer, Dianne Hackborn of the core Android team wrote:

The only memory management that impacts activity lifecycle is the global memory across all processes, as Android decides that it is running low on memory and so need to kill background processes to get some back. If your application is sitting in the foreground starting more and more activities, it is never going into the background, so it will always hit its local process memory limit before the system ever comes close to killing its process. (And when it does kill its process, it will kill the process hosting all the activities, including whatever is currently in the foreground.)

This does not mean that you need to rush out and change your applications. However, if you are running out of heap space, or are just concerned about how much RAM you might be consuming in general, you might wish to take this behavior into account.

Here are some mitigation strategies:

  • Use FLAG_ACTIVITY_REORDER_TO_FRONT or the combination of FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP Intent flags more aggressively, to recycle your existing activity instances where possible. Note that these affect the BACK button navigation, so you will want to ensure that your changes do not harm usability of your app.

  • Roll your own hibernation logic for expensive activities. If an activity has been stopped for some period of time, call setContentView(null) or otherwise cut back on heap consumption. Make note that you did this, so you can restore your state if and when you return to the foreground. You might even consider finishing old activities, if you do not mind them being removed from your BACK stack (if relevant).

  • Use fragments, per Ms. Hackborn’s suggestion in the linked-to StackOverflow answer, as dynamic fragments automatically remove their view hierarchies when they are not on-screen.