[Android] Fix crash adding items to the CollectionView (#7670)

* Fixed 7510 - Crash adding items to the CollectionView on Android

* Removed code used for testing
This commit is contained in:
Javier Suárez Ruiz 2019-12-02 17:20:03 +01:00 коммит произвёл E.Z. Hart
Родитель 5a06dcc721
Коммит a12ed34ff8
3 изменённых файлов: 170 добавлений и 9 удалений

Просмотреть файл

@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
#if UITEST
using Xamarin.Forms.Core.UITests;
using Xamarin.UITest;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.CollectionView)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7510, "CollectionView crashes on adding item", PlatformAffected.All)]
public class Issue7510 : TestContentPage
{
public Issue7510()
{
Title = "Issue 7510";
BindingContext = new Issue7510ModelViewModel();
}
protected override void OnAppearing()
{
if (this.BindingContext is Issue7510ModelViewModel vm)
{
vm.Init();
}
base.OnAppearing();
}
protected override void Init()
{
var infoLabel = new Label
{
Text = "If you press the button and there is no crash, everything goes correctly."
};
var addButton = new Button
{
Text = "Add items",
AutomationId = "AddBtn"
};
addButton.SetBinding(Button.CommandProperty, "MoreCommand");
var collectionView = new CollectionView
{
AutomationId = "Collection",
SelectionMode = SelectionMode.None,
ItemTemplate = CreateDataTemplate()
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Items");
var stack = new StackLayout();
stack.Children.Add(infoLabel);
stack.Children.Add(addButton);
stack.Children.Add(collectionView);
Content = stack;
}
private DataTemplate CreateDataTemplate()
{
DataTemplate template = new DataTemplate(() =>
{
var grid = new Grid() { Padding = new Thickness(0), Margin = 0, RowSpacing = 0, ColumnSpacing = 0 };
grid.RowDefinitions.Clear();
grid.ColumnDefinitions.Clear();
grid.Children.Clear();
var cell = new Label();
cell.SetBinding(Label.TextProperty, "Title");
grid.Children.Add(cell, 0, 0);
return grid;
});
return template;
}
}
[Preserve(AllMembers = true)]
public class Issue7510Model
{
public Guid Id { get; set; }
public string Title { get; set; }
}
[Preserve(AllMembers = true)]
public class Issue7510ModelViewModel : BindableObject
{
private ObservableCollection<Issue7510Model> _items;
public ObservableCollection<Issue7510Model> Items
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged();
}
}
public Command MoreCommand => new Command(async () => await LoadMore());
private async Task LoadMore()
{
await Task.Delay(100);
var postCount = Items.Count();
for (var i = 0; i < 20; i++)
{
Items.Add(new Issue7510Model { Id = Guid.NewGuid(), Title = $"Added Item {postCount + i}" });
Debug.WriteLine(postCount + i);
}
}
internal void Init()
{
var posts = new List<Issue7510Model>();
for (var i = 0; i < 20; i++)
{
posts.Add(new Issue7510Model { Id = Guid.NewGuid(), Title = $"Item {i}" });
}
Items = new ObservableCollection<Issue7510Model>(posts);
}
}
}

Просмотреть файл

@ -1143,6 +1143,7 @@
<DependentUpon>Issue7886.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7898.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7510.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">

Просмотреть файл

@ -14,42 +14,58 @@ namespace Xamarin.Forms.Platform.Android
public void NotifyDataSetChanged()
{
_adapter.NotifyDataSetChanged();
if (IsValidAdapter())
_adapter.NotifyDataSetChanged();
}
public void NotifyItemChanged(IItemsViewSource source, int startIndex)
{
_adapter.NotifyItemChanged(startIndex);
if (IsValidAdapter())
_adapter.NotifyItemChanged(startIndex);
}
public void NotifyItemInserted(IItemsViewSource source, int startIndex)
{
_adapter.NotifyItemInserted(startIndex);
if (IsValidAdapter())
_adapter.NotifyItemInserted(startIndex);
}
public void NotifyItemMoved(IItemsViewSource source, int fromPosition, int toPosition)
{
_adapter.NotifyItemMoved(fromPosition, toPosition);
if (IsValidAdapter())
_adapter.NotifyItemMoved(fromPosition, toPosition);
}
public void NotifyItemRangeChanged(IItemsViewSource source, int start, int end)
{
_adapter.NotifyItemRangeChanged(start, end);
if (IsValidAdapter())
_adapter.NotifyItemRangeChanged(start, end);
}
public void NotifyItemRangeInserted(IItemsViewSource source, int startIndex, int count)
{
_adapter.NotifyItemRangeInserted(startIndex, count);
if (IsValidAdapter())
_adapter.NotifyItemRangeInserted(startIndex, count);
}
public void NotifyItemRangeRemoved(IItemsViewSource source, int startIndex, int count)
{
_adapter.NotifyItemRangeRemoved(startIndex, count);
if (IsValidAdapter())
_adapter.NotifyItemRangeRemoved(startIndex, count);
}
public void NotifyItemRemoved(IItemsViewSource source, int startIndex)
{
_adapter.NotifyItemRemoved(startIndex);
if (IsValidAdapter())
_adapter.NotifyItemRemoved(startIndex);
}
internal bool IsValidAdapter()
{
if (_adapter == null || _adapter.IsDisposed())
return false;
return true;
}
}
}
}