Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[UWP] CollectionView Memory Leak #14780

Merged

Conversation

YZahringer
Copy link
Contributor

@YZahringer YZahringer commented Oct 22, 2021

Description of Change

Unsubscribe from oldElement on TearDownOldElement instead of current Layout/ItemsViewthat is already null.

Issues Resolved

API Changes

None

Platforms Affected

  • UWP

Behavioral/Visual Changes

None

Before/After Screenshots

Not applicable

Testing Procedure

Case 1: Nav back from CollectionView

  1. Take a Memory Snapshot
  2. Navigate to a View that contains a CollectionView
  3. Go back
  4. Take another Memory Snapshot and compare it with the first one
  5. Check that the CollectionView, BindingContext VM, Items VM are released

Case 2: Change ItemsSource of CollectionView

  1. Take a Memory Snapshot
  2. Add items to the CollectionView
  3. Replace the ItemsSource with an empty collection
  4. Take another Memory Snapshot and compare it with the first one
  5. Check that the Items VM are released

Simple project available here: https://github.com/MADSENSE/Madsense.XamarinForms.Sample/tree/collectionview-memory-leak

PR Checklist

  • Targets the correct branch
  • Tests are passing (or failures are unrelated)

@YZahringer YZahringer changed the title [UWP CollectionView Memory Leak [UWP] CollectionView Memory Leak Oct 22, 2021
{
// Stop tracking the old layout
Layout.PropertyChanged -= LayoutPropertyChanged;
oldStructuredItemsView.ItemsLayout.PropertyChanged -= LayoutPropertyChanged;
oldStructuredItemsView.ItemsLayout = null;
Copy link
Contributor Author

@YZahringer YZahringer Oct 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this null assignment, but if we don't do it, the memory leak persists.
I also tried calling SetInheritedBindingContext(oldStructuredItemsView.ItemsLayout, null) instead, without success.

@jsuarezruiz maybe you have an idea or can validate that this should not produce side effects?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Yann! Sorry I only got to this now. I will try and think how we can validate this. I assume you tested this yourself? Are you using this code now in any of your apps by any chance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Gerald, I use the simple project available here with VS Diagnostics Tools to reproduce/check the fix.

For the moment, on production we use an extended renderer as workaround on many apps. Not exactly the same code, because there are private/internal on the base renderer, but the result is the same:

public class ExtendedCollectionViewRenderer : Xamarin.Forms.Platform.UWP.CollectionViewRenderer
{
    protected override void Dispose(bool disposing)
    {
        base.TearDownOldElement(Element);

        if (Element.ItemsLayout is LinearItemsLayout linearItemsLayout)
        {
            Element.ItemsLayout = new LinearItemsLayout(linearItemsLayout.Orientation);
        }
        else if (Element.ItemsLayout is GridItemsLayout gridItemsLayout)
        {
            Element.ItemsLayout = new GridItemsLayout(gridItemsLayout.Span, gridItemsLayout.Orientation);
        }
        else
        {
            Element.ItemsLayout = null;
        }

        base.Dispose(disposing);
    }

    protected override void CleanUpCollectionViewSource()
    {
        var itemContentControls = ListViewBase.GetChildren<ItemContentControl>();
        foreach (var itemContentControl in itemContentControls)
        {
            itemContentControl.FormsDataContext = null;
            itemContentControl.DataContext = null;
        }

        base.CleanUpCollectionViewSource();
    }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the build completes there should be NuGets produced, would you maybe be able to try them out on projects where you have this problem and see if this works as expected and doesn't break anything else? The instructions can be found here. That would be very helpful, thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some tests with the nuget produced on an application with multiple CollectionView on different views, the Memory Leak is solved.
By the way, I also updated the test project.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the cooperation @YZahringer !

@jfversluis
Copy link
Member

jfversluis commented Dec 24, 2021

/azp run

@jfversluis jfversluis added this to Issues in Progress in 5.0.0 SR9 (Planning) - Target Date Jan. 19th via automation Dec 24, 2021
@jfversluis jfversluis moved this from Issues in Progress to PR Needs Review in 5.0.0 SR9 (Planning) - Target Date Jan. 19th Dec 24, 2021
@azure-pipelines

This comment has been minimized.

@azure-pipelines

This comment has been minimized.

@azure-pipelines

This comment has been minimized.

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines

This comment has been minimized.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

3 participants