diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/GitHub15049.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/GitHub15049.cs new file mode 100644 index 00000000000..df2f53f4f4d --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/GitHub15049.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Input; +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; +using System.Runtime.CompilerServices; +using System.ComponentModel; + +#if UITEST +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ +#if UITEST + [NUnit.Framework.Category(Core.UITests.UITestCategories.Github10000)] + [NUnit.Framework.Category(Core.UITests.UITestCategories.CollectionView)] + [NUnit.Framework.Category(Core.UITests.UITestCategories.ManualReview)] +#endif + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Github, 15049, "[Android] CollectionView leaks GREF when items are removed", PlatformAffected.Android, issueTestNumber: 1)] + public class GitHub15049 : TestContentPage + { + protected override void Init() + { + BindingContext = new GitHub15049ViewModel(); + var collectionView = new CollectionView(); + collectionView.ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical); + collectionView.ItemTemplate = new DataTemplate(() => + { + var label = new Label(); + label.SetBinding(Label.TextProperty, "Text"); + + return label; + }); + collectionView.SetBinding(CollectionView.ItemsSourceProperty, "Items"); + Content = collectionView; + } + + public class GitHub15049ViewModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + private ObservableCollection _items; + public ObservableCollection Items + { + get => _items; + set + { + if (_items != value) + { + _items = value; + RaisePropertyChanged(nameof(Items)); + } + } + } + + public bool IsStopped { get; set; } = false; + + public GitHub15049ViewModel() + { + var collection = new ObservableCollection(); + var pageSize = 10000; + + for (var i = 0; i < pageSize; i++) + { + collection.Add(new GitHub15049Model + { + Text = "Item " + i, + }); + } + + Items = collection; + + //Kick off Test + Task.Run(async () => + { + while (Items.Count > 0 && !IsStopped) + { + await Task.Yield(); + + await Device.InvokeOnMainThreadAsync(() => + { + Items.RemoveAt(0); + }); + } + }); + } + + protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public class GitHub15049Model + { + public string Text { get; set; } + } + } +} diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index c5248d7f03e..d64ff3c2091 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -10,6 +10,7 @@ + Issue12603.xaml diff --git a/Xamarin.Forms.Platform.Android/CollectionView/AdapterNotifier.cs b/Xamarin.Forms.Platform.Android/CollectionView/AdapterNotifier.cs index 017b3b45f35..f3ede0c1661 100644 --- a/Xamarin.Forms.Platform.Android/CollectionView/AdapterNotifier.cs +++ b/Xamarin.Forms.Platform.Android/CollectionView/AdapterNotifier.cs @@ -30,8 +30,8 @@ public void NotifyItemInserted(IItemsViewSource source, int startIndex) { _adapter.NotifyItemInserted(startIndex); - var changedCount = _adapter.ItemCount - startIndex; - _adapter.NotifyItemRangeChanged(startIndex, changedCount); + //var changedCount = _adapter.ItemCount - startIndex; + //_adapter.NotifyItemRangeChanged(startIndex, changedCount); } } @@ -41,9 +41,9 @@ public void NotifyItemMoved(IItemsViewSource source, int fromPosition, int toPos { _adapter.NotifyItemMoved(fromPosition, toPosition); - var minPosition = System.Math.Min(fromPosition, toPosition); - var changedCount = _adapter.ItemCount - minPosition; - _adapter.NotifyItemRangeChanged(minPosition, changedCount); + //var minPosition = System.Math.Min(fromPosition, toPosition); + //var changedCount = _adapter.ItemCount - minPosition; + //_adapter.NotifyItemRangeChanged(minPosition, changedCount); } } @@ -59,8 +59,8 @@ public void NotifyItemRangeInserted(IItemsViewSource source, int startIndex, int { _adapter.NotifyItemRangeInserted(startIndex, count); - var changedCount = _adapter.ItemCount - startIndex; - _adapter.NotifyItemRangeChanged(startIndex, changedCount); + //var changedCount = _adapter.ItemCount - startIndex; + //_adapter.NotifyItemRangeChanged(startIndex, changedCount); } } @@ -70,8 +70,8 @@ public void NotifyItemRangeRemoved(IItemsViewSource source, int startIndex, int { _adapter.NotifyItemRangeRemoved(startIndex, count); - var changedCount = _adapter.ItemCount - startIndex; - _adapter.NotifyItemRangeChanged(startIndex, changedCount); + //var changedCount = _adapter.ItemCount - startIndex; + //_adapter.NotifyItemRangeChanged(startIndex, changedCount); } } @@ -81,8 +81,8 @@ public void NotifyItemRemoved(IItemsViewSource source, int startIndex) { _adapter.NotifyItemRemoved(startIndex); - var changedCount = _adapter.ItemCount - startIndex; - _adapter.NotifyItemRangeChanged(startIndex, changedCount); + //var changedCount = _adapter.ItemCount - startIndex; + //_adapter.NotifyItemRangeChanged(startIndex, changedCount); } }