-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix memory leak in CollectionView and CarouselView by using instance-based ItemsLayout defaults #31918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…rtyChanged Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
/backport to release/9.0.1xx-sr12 |
Started backporting to release/9.0.1xx-sr12: https://github.com/dotnet/maui/actions/runs/18353645580 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot revert all changes made to CollectionViewHandler2.iOS.cs
I think we want to take a different approach here.
Can you instead modify the InternalItemsLayoutProperty
properties on ItemsView and CarouselView to use a default create and just return a new instance?
src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs
Outdated
Show resolved
Hide resolved
src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs
Show resolved
Hide resolved
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
Reverted all changes to CollectionViewHandler2.iOS.cs and implemented the alternative approach. Modified |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot it looks like CarouselLayoutTypeConverter will still return the static one as well as ItemsLayoutTypeConverter
Can we make it so the static ItemsLayouts have an internal method we can use to create those defaults?
So for example
public static readonly IItemsLayout CarouselVertical = new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Center
};
should call something called "CreateCarouselVerticalDefault" that's internal and then just use that inside the converters and for the readonly field property as well?
Make that change to all the types that are referenced inside the converters
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
Created internal factory methods in |
/azp run |
Started backporting to release/9.0.1xx-sr12: https://github.com/dotnet/maui/actions/runs/18359232996 |
Azure Pipelines successfully started running 3 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a memory leak in CollectionView caused by static ItemsLayout instances being shared across all CollectionView instances. The fix ensures each view gets its own ItemsLayout instance instead of subscribing to shared static instances.
- Replaced static default ItemsLayout instances with factory methods that create new instances per view
- Updated all converters to use the new factory methods instead of returning static instances
- Enhanced test coverage to verify both CollectionView and handler are properly garbage collected
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
src/Controls/src/Core/Items/LinearItemsLayout.cs | Added internal factory methods for creating default instances and updated static fields to use them |
src/Controls/src/Core/Items/ItemsView.cs | Changed InternalItemsLayoutProperty to use defaultValueCreator with factory method instead of static instance |
src/Controls/src/Core/Items/CarouselView.cs | Updated ItemsLayoutProperty to use defaultValueCreator with factory method |
src/Controls/src/Core/Items/ItemsLayoutTypeConverter.cs | Modified ConvertFrom to use factory methods instead of returning static instances |
src/Controls/src/Core/Items/CarouselLayoutTypeConverter.cs | Updated ConvertFrom to use factory methods for carousel layouts |
src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs | Added comprehensive test to verify both CollectionView and handler are garbage collected |
@copilot seems the tests are failing
|
…erence equality Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>
... Fixed the failing tests in |
/azp run |
Azure Pipelines successfully started running 3 pipeline(s). |
} | ||
|
||
[Fact(DisplayName = "CollectionView Does Not Leak With Default ItemsLayout")] | ||
public async Task CollectionViewDoesNotLeakWithDefaultItemsLayout() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While CollectionView has this GC test, CarouselView lacks a similar explicit test, could create a similar one for CarouselView?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well the way it handles layout is the same no ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added CarouselViewDoesNotLeakWithDefaultItemsLayout
test in CarouselViewTests.iOS.cs
that mirrors the CollectionView test. It verifies both CarouselView and CarouselViewHandler2 are properly garbage collected when using the default ItemsLayout. Changes in commit a3f8b41.
@copilot can you create a DeviceTest for CarouselView similar to
|
Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>
... Created |
/azp run |
Azure Pipelines successfully started running 3 pipeline(s). |
/backport to release/9.0.1xx-sr12 |
Started backporting to release/9.0.1xx-sr12: https://github.com/dotnet/maui/actions/runs/18409998281 |
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description of Change
Fixes a memory leak in CollectionView and CarouselView where static
ItemsLayout
instances were preventing handlers from being garbage collected. The issue occurred because handlers subscribed toPropertyChanged
events on shared static instances likeLinearItemsLayout.Vertical
andLinearItemsLayout.CarouselDefault
.Memory Leak Analysis
The issue manifested as shown in memory dumps where
CollectionViewHandler2
instances were being retained throughPropertyChangedEventHandler
delegates:The root cause was:
InternalItemsLayoutProperty
inItemsView
used staticLinearItemsLayout.Vertical
as the default valueItemsLayoutProperty
inCarouselView
used staticLinearItemsLayout.CarouselDefault
as the default valueItemsLayoutTypeConverter
andCarouselLayoutTypeConverter
) returned static instancesPropertyChanged
events on these static instances viaSubscribeToItemsLayoutPropertyChanged
Changes Made
Created internal factory methods in
LinearItemsLayout
:CreateVerticalDefault()
- creates new vertical LinearItemsLayoutCreateHorizontalDefault()
- creates new horizontal LinearItemsLayoutCreateCarouselVerticalDefault()
- creates vertical carousel layout with snap settingsCreateCarouselHorizontalDefault()
- creates horizontal carousel layout with snap settingsModified
ItemsView.InternalItemsLayoutProperty
:LinearItemsLayout.Vertical
as default valuedefaultValueCreator
withLinearItemsLayout.CreateVerticalDefault()
factory methodModified
CarouselView.ItemsLayoutProperty
:LinearItemsLayout.CarouselDefault
as default valuedefaultValueCreator
withLinearItemsLayout.CreateCarouselHorizontalDefault()
factory methodUpdated
ItemsLayoutTypeConverter.ConvertFrom
:CreateVerticalDefault()
andCreateHorizontalDefault()
factory methodsUpdated
CarouselLayoutTypeConverter.ConvertFrom
:CreateCarouselHorizontalDefault()
andCreateCarouselVerticalDefault()
factory methodsEnhanced tests to verify memory leak fix:
CollectionViewDoesNotLeakWithDefaultItemsLayout
test withWeakReference
trackingCarouselViewDoesNotLeakWithDefaultItemsLayout
test for CarouselViewFixed
ItemsLayoutTypeConverterTests
:Assert.Same
toAssert.IsType
and property checksIssues Fixed
Fixes #25959
Workaround
Before this fix, developers needed to avoid using the default static
ItemsLayout
instances:This workaround is no longer necessary after this fix.
Fixes #29619
Original prompt
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.