Skip to content
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

[Android] Ensure disconnected ItemsViewHandler doesn't hold onto the items source #24610

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static IItemsViewSource Create(IEnumerable itemsSource, BindableObject co
switch (itemsSource)
{
case IList list when itemsSource is INotifyCollectionChanged:
return new ObservableItemsSource(new MarshalingObservableCollection(list), container, notifier);
return new ObservableItemsSource(new MarshalingObservableCollection(list), container, notifier, disposeItemsSource: true);
case IEnumerable _ when itemsSource is INotifyCollectionChanged:
return new ObservableItemsSource(itemsSource, container, notifier);
case IList list:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items
internal class ObservableItemsSource : IItemsViewSource, IObservableItemsViewSource
{
readonly IEnumerable _itemsSource;
readonly bool _disposeItemsSource;
readonly BindableObject _container;
readonly ICollectionChangedNotifier _notifier;
readonly WeakNotifyCollectionChangedProxy _proxy = new();
Expand All @@ -16,9 +17,10 @@ internal class ObservableItemsSource : IItemsViewSource, IObservableItemsViewSou

~ObservableItemsSource() => _proxy.Unsubscribe();

public ObservableItemsSource(IEnumerable itemSource, BindableObject container, ICollectionChangedNotifier notifier)
public ObservableItemsSource(IEnumerable itemSource, BindableObject container, ICollectionChangedNotifier notifier, bool disposeItemsSource = false)
{
_itemsSource = itemSource;
_disposeItemsSource = disposeItemsSource;
_container = container;
_notifier = notifier;
_collectionChanged = CollectionChanged;
Expand Down Expand Up @@ -83,6 +85,14 @@ protected virtual void Dispose(bool disposing)
if (disposing)
{
_proxy.Unsubscribe();

if (_disposeItemsSource)
{
if (_itemsSource is MarshalingObservableCollection marshalingObservableCollection)
marshalingObservableCollection.Dispose();
else if (_itemsSource is IDisposable disposableCollection)
disposableCollection.Dispose();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class MarshalingObservableCollection : List<object>, INotifyCollectionCha
{
readonly IList _internalCollection;
readonly IDispatcher _dispatcher;
readonly WeakNotifyCollectionChangedProxy _proxy;

/// <include file="../../../docs/Microsoft.Maui.Controls/MarshalingObservableCollection.xml" path="//Member[@MemberName='.ctor']/Docs/*" />
public MarshalingObservableCollection(IList list)
Expand All @@ -26,8 +27,7 @@ public MarshalingObservableCollection(IList list)

_internalCollection = list;
_dispatcher = Dispatcher.GetForCurrentThread();

incc.CollectionChanged += InternalCollectionChanged;
_proxy = new WeakNotifyCollectionChangedProxy(incc, InternalCollectionChanged);

foreach (var item in _internalCollection)
{
Expand Down Expand Up @@ -151,5 +151,10 @@ void Reset(NotifyCollectionChangedEventArgs args)

OnCollectionChanged(args);
}

internal void Dispose()
{
_proxy.Unsubscribe();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ await CreateHandlerAndAddToWindow<LayoutHandler>(layout, async (handler) =>
});
}

#if !ANDROID //https://github.com/dotnet/maui/pull/24610
[Fact]
public async void DisconnectedCarouselViewDoesNotHookCollectionViewChanged()
{
Expand Down Expand Up @@ -151,7 +150,6 @@ await CreateHandlerAndAddToWindow<CarouselViewHandler>(carouselView, async (hand

Assert.True(data.IsCollectionChangedEventEmpty);
}
#endif
}

internal class CustomDataTemplateSelectorSelector : DataTemplateSelector
Expand Down
Loading