Home » Android » android – Images added to AnimationDrawable programmatically leak memory

android – Images added to AnimationDrawable programmatically leak memory

Posted by: admin June 15, 2020 Leave a comment


I have an android App with plenty of animations.

When I programmatically create animations (using AnimationDrawable) the non-java object (as appears in DDMS Heap tab) grows with every new animation I load and never shrinks back even after my animations get released.

I have only one reference to each AnimationDrawable object from a wrapper object I wrote and I verified this object gets released by overriding the finalize method and making sure it gets called.

Eventually android stops loading images and prints “out of memory” errors to the log.

The interesting thing is that this happens only in some devices (Motorola Xoom, Sony Experia) and not in others (such as the Galaxy S).

This problem is not specific Honeycomb or pre-Honeycomb as you can see from the device examples I gave.

Some of the things I tried:

  1. Calling recycle on each of the frames after I am done with the current animation but it doesn’t seem to help.
  2. Assigning null to the AnimationDrawble object
  3. Making sure that there are no static variable related to the class holding the reference to the animation drawable
  4. Make sure the problem disappears once I comment out myAnimation.addFrame(...)
How to&Answers:

This isn’t an exact answer, but rather a helpful hint to find where the exact leak is occurring. Perform a heap-dump after you expect your memory to be reclaimed and see why the objects you think should be dead are still alive.

Make sure you get the memory analyzer tool for eclipse. (http://www.eclipse.org/mat/)


There could be two possible reason, first at the time of creating the bitmap and second when you are converting the bitmap into the BitmapDrawable. As i can see from your comment (new BitmapDrawable(currentFrameBitmap) now this method is depreciated better to use BitmapDrawable(getResources(),currentFrameBitmap) Without the Resources reference, the bitmap may not render properly, even when scaled correctly. To load bitmap efficiently you can scale it properly.

public class BitmapDecoderHelper {
private Context context;
public BitmapDecoderHelper(Context context){
    this.context = context;
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
Log.d("height reqheight width reqwidth", height+"//"+reqHeight+"//"+width+"///"+reqWidth);
if (height > reqHeight || width > reqWidth) {
    if (width > height) {
        inSampleSize = Math.round((float)height / (float)reqHeight);
    } else {
        inSampleSize = Math.round((float)width / (float)reqWidth);
return inSampleSize;
public Bitmap decodeSampledBitmapFromResource(String filePath,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;

    BitmapFactory.decodeFile(filePath, options);
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    Log.d("options sample size", options.inSampleSize+"///");
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    // out of memory occured easily need to catch and test the things.
    return BitmapFactory.decodeFile(filePath, options);
public int getPixels(int dimensions){
    Resources r = context.getResources();
    int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensions, r.getDisplayMetrics());
    return px;
public String getFilePath(Uri selectedImage){
    String[] filePathColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = context.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    String filePath = cursor.getString(columnIndex);
    return filePath;