Memory Cache – Part 1
Previously on Styling Android we have discussed how important it is to make your app as fast as possible because making your user wait for things to happen is a sure way to drive them away from your app. Also, you have to be quite careful when it comes to using images within your app because images tend to be relatively large and even minor inefficiencies in image handling can have a major impact on your app. In this series of articles we’re going to look at a technique of using a memory cache for images to avoid having to hold multiple copies of the same image in memory when that image is used multiple times in your layout.
Before we begin, let’s have a quick reminder about how Android and Java memory management works. Strictly speaking the JVM does not necessarily use reference counts for each object as described below, however this is a useful metaphor to help understand how Garbage Collection works, so we’ll use it for the sake of clarity.
The following code does a number of things:
String string = new String();
Firstly the new keyword allocates the memory for, initialises and calls the constructor on a new String object. The second thing that it does is create a reference to that new String object which is assigned to the variable named string. When this reference is made, a reference count on the String object is incremented. When the string variable goes out of scope (i.e. it’s a local variable in a method, and we return from the method), or is changed to reference a different object, or is
nulled, then the reference is to the String object destroyed and the reference count on the String object is decremented. We can also create new references to the same object:
String newRef = string;
This will cause the reference count on the String object to be incremented again.
The Java VM has a garbage collector which runs periodically (and specifically when memory is getting low). The garbage collector looks for objects which have a reference count of 0 (i.e. all of the references to that object have gone out of scope) and it destroys these objects thus freeing up the memory that they are using. This is known as the object being garbage collected (or GC’d).
When we create these references to the String object, they are “strong” references which means that the existence of one or more strong references to a given object is enough to prevent that object from being GC’d. There is another kind of reference, a weak reference, which still permits us access to an object, but the existence of the weak reference will not prevent the object that it references from being GC’d. I am not going to give a detailed introduction to weak references, but if you want to know more then there is an excellent description of them here. There are also other kinds of reference which are subtly different from weak references (soft & phantom references) which are beyond the scope of our discussion.
Now that we know what a weak reference is how do we go about creating one? The answer is using the java.lang.ref.WeakReference class. This is a generic class which takes the class of the object that we want to create a reference to as its generic type:
String string = new String(); WeakReference<String> wr = new WeakReference<String>( string);
We now hold both a strong reference (though our string variable) and a weak reference (through our wr variable) to the String object. We can access the object itself via the weak reference by calling its
String newRef = wr.get();
This will effectively create another strong reference to the String object.
On the face of it, weak references sound rather dangerous. What happens if I try and access the referenced object after it has been GC’d? Well it’s actually not that bad. The
get() method of wr will simply return
null. As long as we properly handle a
null then everything is fine.
Now that we understand a bit about weak references, we can look at building an in-memory image cache which will allow us to re-use bitmaps that have already been loaded in to memory which saves both image loading time, and reduces memory consumption. In the next part of this series we’ll start putting this knowledge in to practice.
© 2012, Mark Allison. All rights reserved. This article originally appeared on Styling Android.
Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License
Memory Cache – Part 1 by Styling Android, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. Terms and conditions beyond the scope of this license may be available at blog.stylingandroid.com.