On Jun 18, 2012, at 10:16 AM, Matthew Leibowitz wrote:
> As my last question suggested, I am working with images. I cache the lo res 
> in an array member of a view, but how do I dispose of the images?

By Dispose()ing of them. :-)

> I tried overriding the Dispose(bool) method, but that doesn't seem to be 
> called when the Activity is closed.

Dispose(bool) is called by the GC when the value can be collected. This will be 
some point after the Activity is closed, but not immediately after, unless you 
null out your Bitmap fields and call GC.Collect() in Activity.OnDestroy(). 
(Even GC.Collect() may not work immediately, and would still require that you 
null out all Java.Lang.Object-subclass fields...)

> What am I doing wrong? :) Is there another method/place? 

> The "dispose" should be called when the containing activity is closed, but I 
> don't want either the Activity or the View to know about each other.
> This is because they are used in a few places, but in slightly different ways.

I'm not entirely sure how your View is obtaining the array from your 
Activity...but it might not matter.

Let's assume you have code such as [0]:

        Bitmap[] bitmaps = new Bitmap[100];
        for (int i = 0; i < 100; i++) {
                bitmaps[i] = BitmapFactory.DecodeFile(...);
        } 

Every Bitmap instance will contain a gref, and gref acts as a GC "root", 
preventing the Java VM from collecting the Java-side object [1]. The above will 
thus necessitate that 100 gref's exist until all 100 Bitmaps instances are 
Dispose()d, OR the GC is able to collect all of them:

        for (int i = 0; i < bitmaps.Length; i++)
                bitmaps [i].Dispose ();

Can you do better? Somewhat:

        JavaList<Bitmap> bitmaps = new JavaList<Bitmap>();
        for (int i = 0; i < 100; i++) {
                using (var bitmap = BitmapFactory.DecodeFile (...))
                        bitmaps.Add (bitmap);
        }

The `using` ensures that the managed Bitmap peer instance is disposed of ASAP. 
The above code will require only 1 gref: the gref for the JavaList<Bitmap> 
instance.

When you access `bitmaps`, a new managed peer will be created, which will 
acquire a new gref:

        Bitmap b = bitmaps [0];

To ensure that the gref is disposed of as quickly as possible, you'd still want 
to Dispose() of it:

        using (var b = bitmaps [0])
                DoSomethingWithTheBitmap (b);

However, since JavaList<Bitmap> still has a gref, everything it references will 
also be kept alive. You'll have 1 gref, but you still have 100 Bitmap instance 
hanging around at once. To allow Dalvik to collect them, you need to release 
the gref:

        bitmaps.Dispose ();

The `bitmaps.Dispose()` call could thus go in Activity.OnDestroy()

 - Jon

[0] 
http://stackoverflow.com/questions/11081806/larger-memory-footprint-when-using-bitmapfactory-decodefile-in-c-sharp-and-huge

[1] http://docs.xamarin.com/android/advanced_topics/garbage_collection

_______________________________________________
Monodroid mailing list
Monodroid@lists.ximian.com

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid

Reply via email to