Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recycling Bitmap does not free memory

I have an Activity in a TabHost with 3 other activities. Hence, these are always alive (or in "on pause" state).

The first activity has four different images (~250kb each) and they are retrieving a lot of memory (around 80MB. Just to point out, I load the minimum size needed for the screen and I'm using layout_weight if that helps), so I want to minimize the amount of memory which is needed.

I already tried to delete the images on the OnPause state and set them again on OnResume, but I didn't have luck, this is one example of what I was trying to do:

 imageView.Drawable.Callback = null;
 ((BitmapDrawable)imageView.Drawable).Bitmap.Recycle();
 imageView.Drawable.Dispose();
 imageView.SetImageDrawable(null);
 imageView.SetImageBitmap(null);
 GC.Collect();

I don't know if deleting the Bitmap on OnPause is the best strategy, but it should work. I don't understand why the ImageView isn't collected by the GC (since there are not external references)

EDIT This is how I'm loading the images. It doesn't work even if I put the images on the xml file. Besides, I don't care this code, I just want to dispose the bitmaps.

       void SetBackgroundImages(int imageId, int resId, float width, float height) {
        var imageView = FindViewById<ImageView>(imageId);
        using (var bitmap = DecodeSampledBitmapFromResource(Resources, resId, width, height))
            imageView.SetImageBitmap(bitmap);

    }
    public static Bitmap DecodeSampledBitmapFromResource(Resources res, int resId, float reqWidth, float reqHeight) {

    var options = new BitmapFactory.Options {InJustDecodeBounds = true};
    using (var b = BitmapFactory.DecodeResource(res,resId,options)){}
        options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);
        options.InJustDecodeBounds = false;
        return BitmapFactory.DecodeResource(res, resId, options);
    }
like image 572
Adam Avatar asked Dec 23 '13 03:12

Adam


People also ask

What does bitmap recycle do?

The recycle() method allows an app to reclaim memory as soon as possible. Caution: You should use recycle() only when you are sure that the bitmap is no longer being used. If you call recycle() and later attempt to draw the bitmap, you will get the error: "Canvas: trying to use a recycled bitmap" .

How do you handle bitmap in Android as it takes too much memory?

Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.

How do you clear a bitmap?

You can use eraseColor on bitmap to set its color to Transparent. It will useable again without recreating it.

What is bitmap pooling in Android?

Glide Bitmap Pool is a memory management library that allows you to reuse bitmap memory. Because it reuses bitmap memory, there is no need to invoke the Garbage Collector repeatedly, resulting in a smoother functioning program. On supported Android versions, it decodes the bitmap using inBitmap.


2 Answers

At the end calling to java.lang.System.gc() after deleting the images did the trick.

like image 82
Adam Avatar answered Oct 04 '22 06:10

Adam


using (var imageView = FindViewById<ImageView>(Resource.Id.imageView1))
    using (var bitmap    = Android.Graphics.BitmapFactory.DecodeResource(
            this.Resources, Resource.Drawable.Icon))
        imageView.SetImageBitmap(bitmap);

i saw this approach in several places, another one is the use of WeakReference to ImageView. These approaches can help GC to collect reference to ImageView properly

like image 20
showyoumuck Avatar answered Oct 04 '22 06:10

showyoumuck