Search code examples
javaandroidmemory-leaksbitmapweak-references

What are the benefits to using WeakReferences?


I have some memory leaks in my app. They all originate around a specific view cluster that I have spent a loooot of time tweaking and trying to reduce a much contextual passing as possible. This leads me to believe that bitmaps used in the cluster are the issue. So I was thinking to use WeakReferences for all references to the bitmaps used by the views. I have never used a WeakReference and am not sure if this is a good application. Can any body provide an helpful pointers or tips?


Solution

  • So I was thinking to use WeakReferences for all references to the bitmaps used by the views. I have never used a WeakReference and am not sure if this is a good application. Can any body provide an helpful pointers or tips?

    Be careful, this is dangerous in your case. The GC could get rid of all your bitmaps while your application may still need them.

    The key issue about WeakReference is to understand the difference with hard references. If there is no more hard reference to a bitmap in your application, then the GC is allowed to atomically remove the object from memory and all existing weak reference will instantaneously point to null. In your case, you CANNOT use weak references all over your code.

    Here is an idea of the solution. Create a container object that will keep weak references (only) to all your bitmaps. Your views should always reference bitmaps with hard references only. When a view creates a bitmap, it should register it in the container object. When it wants to use a view, it should obtain a hard reference from the container.

    Like that, if no views is referring to a bitmap, then the GC will collect the object without side effects for views, since none has a hard reference to it. When using weakly referenced objects, it is good practice to explicitly set hard references to null when you don't need the object anymore.

    Addition

    Here is a quick implementation of the solution (just to give an idea):

    public class BitmapContainer {
    
        public static class Bitmap {
            private final long id;
            public Bitmap(long id) { this.id = id; }
            public long getId() { return id; }
            public void draw() { };
        }
    
        WeakHashMap<Bitmap, WeakReference<Bitmap>> myBitmaps
            = new WeakHashMap<Bitmap, WeakReference<Bitmap>>();
    
        public void registerBitMap(Bitmap bm) {
    
            if ( bm == null ) throw new NullPointerException();
    
            WeakReference<Bitmap> wr = new WeakReference<Bitmap>(bm);
            myBitmaps.put(bm, wr);
    
        }
    
        /** Method returns null if bitmap not available */
        public Bitmap getBitMap(long id) {
    
            for ( Bitmap item : myBitmaps.keySet() ) {
                if ( item != null) {
                    if ( item.getId() == id ) {
                        return item;
                    }
                }
            }
    
            return null;
    
        }
    
    }