Xamarin.Forms.Image Leaks Like A Sieve On Android

OK - I've spent two days googling and tearing my hair out.

Whatever I do I can't seem to get memory reclaimed from an Image on Android. I've tried subclassing and using my own custom render with the following 'belt and braces' style approach...

protected override void Dispose (bool disposing)
{
        if (disposing && !_disposed)
        {
            _disposed = true;

            ImageView i = Control;
            BitmapDrawable d = i.Drawable as BitmapDrawable;

            if (d != null)
            {
                Bitmap bitmap = d.Bitmap;
                if (bitmap != null)
                {
                    bitmap.Recycle ();
                    bitmap.Dispose ();
                }
            }
            i.SetImageBitmap (null);
            i.SetImageDrawable (null);
        }
        base.Dispose (disposing);
    }
}

.. and this is getting called but the memory still Doesn't get reclaimed. GC.Collect() is no help.

Have also tried FFImageLoader, this is much more efficient but the memory used by image views still isn't reclaimed even if I tell to to clear the cache (and I can tell the cache is cleared because a new version of the image is loaded and memory usage increases again).

Is there any sure-fire solution to reclaim the memory used by an ImageView on Android or am I stuck with setting largeheap="true" and just hoping my users don't browse enough images to cause the app to crash!

Posts

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Simplest solution is usually the right one.
    Is it possible you're so busy looking at the image you're missing a use of the image? Maybe it just isn't passing out of scope yet and something someplace still has ahold of it.

    With the abundance of people doing image browsers and editors and photo apps etc. I would ASSUME that a framework-wide issue like that would have come up and been screamed about by many people by now.

  • JamesClossJamesCloss GBMember ✭✭

    I have been thinking about that as well and am 99% sure this is not the issue - if it was just some pointer to the image hanging around then surely Dispose() would never get called on the renderer?

  • JamesClossJamesCloss GBMember ✭✭

    Hmmm - on further investigation it seems the leak may be down to CarouselView. Doesn't look like I'm getting a leak with images in a standard layout...

    I don't suppose anyone is aware of any memory issues/workarounds with CarouselView? A quick search seems to show that other people are also having issues.

  • JamesClossJamesCloss GBMember ✭✭

    Well, I figured out a workaround. It's pretty hacky but it stops the leaks...

    The DataTemplate in CarouselView is my own custom class that is a Subclass of Grid, call it MyDataTemplate. When one of these is added to a parent view ( OnSizeAllocated ) I perform a recursive callback to figure out the parent page and register the DataTemplate with the parent page.

    When I am sure I don’t need the page any more I loop through all the registered MyDataTemplate instances and call a FreeMemory() method on them, this removes all the children from the Grid (including the Image instances) and seems to prevent any memory leaks.

    It’s pretty hacky but it works!

  • NMackayNMackay GBInsider, University mod

    @JamesCloss said:
    Well, I figured out a workaround. It's pretty hacky but it stops the leaks...

    The DataTemplate in CarouselView is my own custom class that is a Subclass of Grid, call it MyDataTemplate. When one of these is added to a parent view ( OnSizeAllocated ) I perform a recursive callback to figure out the parent page and register the DataTemplate with the parent page.

    When I am sure I don’t need the page any more I loop through all the registered MyDataTemplate instances and call a FreeMemory() method on them, this removes all the children from the Grid (including the Image instances) and seems to prevent any memory leaks.

    It’s pretty hacky but it works!

    Thanks for reporting back your findings, it'll help others.

Sign In or Register to comment.