dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.24k stars 1.76k forks source link

Memory Leak issues with CollectionView with elements with Behavior and VisualStateGroup #21216

Open leoslima13 opened 8 months ago

leoslima13 commented 8 months ago

Description

We have noticed several memory leak problems when using CollectionView, especially when controls have a VisualStateGroup declared globally for the elements.

We also noticed that the Behaviors attached to elements within the CollectionView are not unattached when the page is removed from the navigation stack. I noticed that in the .net MAUI documentation they recommend releasing/removing behaviors manually, but it is practically impossible to do this in the CollectionView, since the items are virtualized. A possible workaround is to observe the ChildAdded and ChildRemoved events and make a local copy of them and release/clear the behaviors when the CollectionView is destroyed

You can compare on this sample, commenting out the global style lines on Styles.xaml file But we can also see the difference without the CustomBehavior created to dispose elements inside the CollectionView as you can see on MainProgram.cs

Removing the lines below you will notice that the memory is never free after navigations CollectionViewHandler.Mapper.AppendToMapping("DisposableCollection", (handler, view) => { view.Behaviors.Add(new DisposableBehavior()); });

The sample is very intuitive, we have two buttons to force GC to collect and also another one to check the Memory size of the application, you can notice that without the DisposableBehavior attached on CollectionView, even clicking on GC Collect button after navigating back until the first page, the memory will still be allocated with "Dead Objects".

Steps to Reproduce

1 - Create new blank Maui App 2 - Create a Page with a CollectionView with a DataTemplate for a couple of elements, like Grid/HorizontalSL/VerticalSL with Entry and Label and a Button 3 - Navigate to another page or a new instance of the same page, many times, like 4 or 5 times 4 - You'll noticed that the Memory is not being free after the pages goes out from NavigationStack

Link to public reproduction project repository

https://github.com/leoslima13/MauiLeakRepro

Version with bug

8.0.7 SR2

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android, Windows

Affected platform versions

iOS 17.2, Android 13, Windows 10/11

Did you find any workaround?

No workarounds, actually we're starting to remove global styles and applying the styles locally file by file using x:Key. And for behaviors, we're getting the instance of the page removed from navigation stack, and iterate item by item to remove all behaviors applied, and the same process for the items inside the CollectionView

Relevant log output

No response

RoiChen001 commented 8 months ago

Can repro this issue at Windows platform on the latest 17.10.0 Preview 2.0.

ESO-ST commented 6 months ago

Isn't that because your old page still exists when you navigate away to your new page? since you can navigate back to it if you press back.

If you press back to navigate back to the previous page, you will notice that now the behaviors will be detached and your destructors will get called (when the GC kicks or if you force it), that's what I've noticed running this on an iPad.

@PureWeen is that correct, or is there in fact a memory leak with CollectionView ?