From 4b19d49aa228330af37cee8c4d4fe7097eaf608d Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Tue, 24 Jan 2017 04:48:36 -0700 Subject: [PATCH] Add check for disposed gesture detector on VisualElementRenderer (#706) --- .../Bugzilla45330.cs | 119 +++++++++++++++++++++ .../Xamarin.Forms.Controls.Issues.Shared.projitems | 1 + .../VisualElementRenderer.cs | 6 ++ 3 files changed, 126 insertions(+) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla45330.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla45330.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla45330.cs new file mode 100644 index 0000000..d3a05fd --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla45330.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.ObjectModel; +using System.Linq; +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 45330, "System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Android.Views.GestureDetector'.", PlatformAffected.Android)] + public class Bugzilla45330 : TestContentPage + { + ObservableCollection<_45330Notification> _feed; + + [Preserve(AllMembers = true)] + public class _45330Dto + { + public _45330Dto() + { + Notifications = new ObservableCollection<_45330Notification>(); + } + + public ObservableCollection<_45330Notification> Notifications { get; set; } + } + + [Preserve(AllMembers = true)] + public class _45330Notification + { + public string UniqueId { get; set; } + public DateTime DisplayDate { get; set; } + } + + [Preserve(AllMembers = true)] + public class _45330ListCell : ViewCell + { + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + + var item = BindingContext as _45330Notification; + if (item == null) return; + + View = new StackLayout() + { + BackgroundColor = Color.Transparent, + Padding = new Thickness(0, 1, 0, 1), + Children = { new Label { Text = item.UniqueId } } + }; + } + } + + public ObservableCollection<_45330Notification> Feed + { + get { return _feed; } + set + { + _feed = value; + OnPropertyChanged(); + } + } + + protected override void Init() + { + BindingContext = this; + Feed = MakeNotifications(); + + var listview = new ListView(); + listview.SetBinding(ListView.ItemsSourceProperty, "Feed"); + listview.ItemTemplate = new DataTemplate(typeof(_45330ListCell)); + listview.IsPullToRefreshEnabled = true; + listview.RefreshCommand = new Command(() => + { + listview.IsRefreshing = false; + Feed = MakeNotifications(); + }); + + listview.ItemAppearing += (sender, e) => + { + var currentItem = e.Item as _45330Notification; + if (currentItem == null) return; + var item = Feed.Last(); + if (currentItem.UniqueId == item.UniqueId) + { + Feed = MakeNotifications(); + } + }; + + var layout = new StackLayout(); + + var instructions = new Label { Text = @"The bug can be intermittently reproduced by pulling the list down to refresh it and immediately tapping one of the cells. +Leaving this test page in for reference purposes, and possibly as a base for a future UI test if we get a way to accurately/consistently simulate the events which cause the crash."}; + + layout.Children.Add(instructions); + layout.Children.Add(listview); + + Content = layout; + } + + ObservableCollection<_45330Notification> MakeNotifications() + { + var list = new _45330Dto(); + for (int i = 0; i < 1000; i++) + { + list.Notifications.Add(new _45330Notification() + { + UniqueId = i.ToString(), + DisplayDate = DateTime.UtcNow + }); + } + return list.Notifications; + } + + protected override void OnAppearing() + { + base.OnAppearing(); + Feed = MakeNotifications(); + } + } +} \ No newline at end of file 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 ba7de6c..c459401 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 @@ -149,6 +149,7 @@ + diff --git a/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs b/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs index f67eb66..19b05e2 100644 --- a/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs +++ b/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs @@ -106,6 +106,12 @@ namespace Xamarin.Forms.Platform.Android _gestureListener?.OnTouchEvent(e); + if (_gestureDetector.IsValueCreated && _gestureDetector.Value.Handle == IntPtr.Zero) + { + // This gesture detector has already been disposed, probably because it's on a cell which is going away + return handled; + } + return _gestureDetector.Value.OnTouchEvent(e) || handled; } -- 2.7.4