user3915477
user3915477

Reputation: 275

Xamarin.Forms: ListView Not Recycling Cells

I am using a ListView to display a long list of custom ViewCells. I am using ListViewCachingStrategy.RecycleElement so as to only load the visible cells and recycle them as they leave the screen. It's not working.

A breakpoint in my custom viewcell's constructor shows it getting called for as many times as there are items in the ListView's ItemSource so I know it's instantiating a cell for every item instead of just the visible ones. That's not right. Also if my cell's are memory heavy enough then the app crashes because it can't allocate enough memory for all the cells.

Here is my ListView

    menuContainer.Content = new ListView(ListViewCachingStrategy.RecycleElement) 
    {
        ItemsSource = menuItems, // about 800 objects
        ItemTemplate = new DataTemplate(typeof(CustomCell)),
        RowHeight = (int)menuItemGridHeight 
    };

And here is my custom ViewCell, just a grid with a button

    class CustomCell : ViewCell
    {
        public CustomCell()
        {
            Button button = new Button
            {
                BorderRadius = 0,
                BackgroundColor = Color.Transparent
            };

            Grid grid = new Grid
            {
                ColumnSpacing = 0,
                BackgroundColor = Color.FromRgba(255, 255, 255, 0.8),
                ColumnDefinitions = new ColumnDefinitionCollection
                {
                    new ColumnDefinition { Width = new GridLength(15, GridUnitType.Star) },
                    new ColumnDefinition { Width = new GridLength(100, GridUnitType.Star) }
                }
            };

            grid.Children.Add(button, 1, 0);

            View = grid;
        }
    }

On Android Emulator I get a Java.Lang.OutOfMemoryError. iOS seems to have enough spare memory to not crash. I also verified that the app is loading all of the objects in ItemSource just fine, so I know the problem is allocating memory for all the cell objects, not the ItemSource objects.

Why won't my ListView recycle its ViewCells?


Edit: Here is code that works. The cells get recycled as they should and also maintain the proper height.

The ListView...

ListView(ListViewCachingStrategy.RecycleElement) 
    {
        ItemsSource = menuItems, // about 800 objects
        ItemTemplate = new DataTemplate(typeof(CustomCell)),
        HasUnevenRows = true
    };

And the custom view cell...

    class CustomCell : ViewCell
    {
        public CustomCell()
        {
            Height = 100;

            Button button = new Button
            {
                BorderRadius = 0,
                BackgroundColor = Color.Transparent
            };

            Grid grid = new Grid
            {
                ColumnSpacing = 0,
                BackgroundColor = Color.FromRgba(255, 255, 255, 0.8),
                ColumnDefinitions = new ColumnDefinitionCollection
                {
                    new ColumnDefinition { Width = new GridLength(15, GridUnitType.Star) },
                    new ColumnDefinition { Width = new GridLength(100, GridUnitType.Star) }
                }
            };

            grid.Children.Add(button, 1, 0);

            View = grid;
        }
    }

Upvotes: 0

Views: 969

Answers (1)

Damian
Damian

Reputation: 4763

When I put together a sample based on your code, with a thousand items I only get six cells created, unless menuItemGridHeight (RowHeight) is too small, in which case I get a thousand cells instanciated.

Can you check menuItemGridHeight? I'd consider removing setting the RowHeight property altogether.

Values of 0 or 1 get your behavior ... 100 does not ... not sure where the cutoff lies, but I assume that when deciding whether it can re-use cells, it looks to see if the existing cell will fit the content for the new item to be rendered.

Upvotes: 1

Related Questions