Memory management

Every Java developer has heard of the garbage collector (GC); this is a mechanism that automatically frees the resources in memory for us. On some occasions, we can prevent the garbage collector from freeing some resources; if the resources keep growing, we will inevitably see OutOfMemoryError.

If this happens, we need to locate the leak and then stop it. In this section, we will take a look at how to locate the source of the problem and a series of good practices to prevent this from happening.

This is not something to look into only when an error has occurred; our app might have leaks, not big enough to be detected with a quick test, that can lead to an error in a device with a smaller memory heap. Therefore, it's good to do a quick check on the memory levels before releasing an app.

Detecting and locating leaks

Android Studio provides a quick way to check the memory status. At the bottom window, you will find a tab called Memory next to logcat and the ADB logs.

Detecting and locating leaks

If you click on the small truck icon, which we call the garbage collector, you will see how the free memory increases.

Don't take this as a reference to the free memory because the heap is dynamic. This means that the heap can be 64 MB at first; we have 60 MB allocated and 4 MB free, but we allocate 10 MB more. The heap can grow higher, and we will end up having a 128 MB heap, with 70MB allocated and 58 MB free.

To detect a leak, we need to take the reference of the memory allocated. Click on the garbage collector constantly and navigate through the app, open and close activities, load images, scroll the lists, and perform these actions multiple times. If the allocated memory keeps growing and never goes down, it means that we are leaking memory and preventing some resources from being collected. We can roughly locate in which activity or fragment the leak is happening as we will see the increase always at the same point (assuming we don't have more than one leak).

To locate the source more precisely, we need to use Android Device Monitor:

Detecting and locating leaks

Select your app process and click on Update Heap:

Detecting and locating leaks

Once this is selected, we can see the allocations of the objects; this will be a good lead in case of bitmap or thread leaks:

Detecting and locating leaks

If we still have no clear idea of what is leaking the memory, we can click on the Dum HPROF file button and open this file with MAT, a memory analyzer tool from Eclipse. We will have to download Eclipse for this.

When we import the file, we can double-click in our process and click on List Objects, which will identify what is happening. For instance, we can see how many objects we have in an activity and how much heap is being used:

Detecting and locating leaks

Preventing leaks

Better than fixing a memory leak is to not have it in the first place. If, during development, we keep in mind the most common causes of leaks, this will save us problems in the future.

Activity and context references

Activity references are one of the main causes of this problem. It's very common to send a reference of our activity to a download listener or to an event listener. If a reference to our activity is held in another object, this will prevent the garbage collector from freeing our activity. For instance, if we change the orientation, our activity will be created again by default, and the old activity with the old orientation will be destroyed.

Remember to unsubscribe from the listeners in the onDestroy method of our Activity and keep an eye on the objects where you send the Context; this is a strong reference to our Activity.

Using WeakReference

By default, when we create an object in Java, it is created with a hard reference. Objects different from null with hard references won't be garbage collected.

An object that contains only weak references will be garbage collected in the next cycle. The same object can have more than one reference; therefore, if we need to use an object temporarily, we can create a weak reference to it, and when the hard references are removed, it will be garbage collected.

This is a real-world example included in the Facebook SDK source code. They create a custom popup called ToolTipPopup, which looks similar to the following image:

Using WeakReference

This popup needs an anchor view, and this anchor view is referenced with a weak reference:

private final WeakReference<View> mAnchorViewRef;

The reason behind this is that by the time the popup is shown, we don't need the anchor view anymore. Once the popup is displayed, the anchor view can be set to null or made to disappear, and it won't affect us. Therefore, with a weak reference, if the original anchor view is destroyed and loses its hard references, it will also free the weak referenced object in the ToolTipPopup class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset