Forum Xamarin.Forms

ListViewRenderer not garbage collected on android?

I have been trying to hunt down a memory leak issue on Android for the past few days, occurring when I navigate back and forth between certain pages. During this quest I have created a minimal Xamarin.Forms PCL app to try and recreate the problem that I'm experiencing, and I've found out the following. I would like to get your opinion on whether this is expected behaviour and I'm doing something wrong, or if it's a bug in Xamarin.Forms.

The basic issue seems to be that the same page being shown multiple times results in its ListViewRenderer not being garbage collected.

I have two pages, a main navigation page and a child page. The main page is a simple ContentPage (the default page), and the child page contains a ListView with ImageCells showing the Xamarin icon:

namespace MemoryTest
{
    class ImageVM
    {
        public string Source { get; set; }
    }

    public class ChildPage : ContentPage
    {
        public ChildPage()
        {
            var template = new DataTemplate(typeof(ImageCell));
            template.SetBinding(ImageCell.ImageSourceProperty, nameof(ImageVM.Source));
            var listView = new ListView
            {
                ItemTemplate = template,
                ItemsSource = Enumerable.Repeat(new ImageVM { Source = "icon.png" }, 20).ToList()
            };
            Content = listView;
        }
    }
}

In the App constructor I configure a Timer to navigate back and forth between the two pages

var childPage = new ChildPage();
var navigationPage = new NavigationPage(content);
MainPage = navigationPage;

var childVisible = false;
Device.StartTimer(TimeSpan.FromSeconds(0.5), () =>
{
    if (childVisible)
    {
        navigationPage.PopAsync();
    }
    else
    {
        navigationPage.PushAsync(childPage);
    }
    childVisible = !childVisible;
    return true;
});

The entire app (it's quite small) is available on my github page (troelsim/MemoryTest)

This will consume more and more memory, and eventually fail with a Java.Lang.OutOfMemoryError, a full stack trace can also be seen on my github page.

I can't use the Xamarin Profiler (don't have enterprise), but the Android Profiler from Android Studio shows that "Java" memory is clearly rising monotonically as the app runs. Screenshot in the github repo I can't link to.

... And a Java heap dump reveals that certain Renderer classes, for instance the ListViewRenderer seem not to be garbage collected. Forcing GC from the android profiler doesn't help. Screenshot in the github repo.

This occurs using Xamarin.Forms 2.3.4.224, and on android 7.0 as well as 6.0.1 which are the ones I've tested.

What puzzles me is that I get a leak even though I don't allocate anything during the navigation. Is it my responsibility that Xamarin.Forms cleans up the renderer's resources e.g. when I navigate away from a page containing images?

I've made the same app without the ListView and there's no problem.

I hope someone can point me in the right direction. This (or a similar) problem happens in our product when the user has been navigating around for a while.

Answers

Sign In or Register to comment.