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);
}
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" .
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.
You can use eraseColor on bitmap to set its color to Transparent. It will useable again without recreating it.
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.
At the end calling to java.lang.System.gc()
after deleting the images did the trick.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With