diff options
author | Samantha Houts <samhouts@users.noreply.github.com> | 2017-10-18 14:28:18 -0700 |
---|---|---|
committer | Rui Marinho <me@ruimarinho.net> | 2017-10-18 22:46:09 +0100 |
commit | 3b9712aaf5d0e8932d1e30facc9ec842a43f6860 (patch) | |
tree | 71b91ca39de0c0fc9ad3e5cebe42755c8d3b9e94 /Xamarin.Forms.Platform.Android | |
parent | 0927f1e6889a2f92864c8bfc384cfd4c3fa9c7ed (diff) | |
download | xamarin-forms-3b9712aaf5d0e8932d1e30facc9ec842a43f6860.tar.gz xamarin-forms-3b9712aaf5d0e8932d1e30facc9ec842a43f6860.tar.bz2 xamarin-forms-3b9712aaf5d0e8932d1e30facc9ec842a43f6860.zip |
[Android] Prevent ObjectDisposedExceptions in ListViews with Header/FooterTemplates (#1155)
* Update repro to include header/footers with bound props
* [Android] Clear renderers of ListView header/footers
And don't call `RemoveAllViews`, because that causes the ObjectDisposedExceptions.
Diffstat (limited to 'Xamarin.Forms.Platform.Android')
-rw-r--r-- | Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs | 91 |
1 files changed, 66 insertions, 25 deletions
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs index d9f06c54..7be10535 100644 --- a/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs @@ -14,6 +14,7 @@ namespace Xamarin.Forms.Platform.Android public class ListViewRenderer : ViewRenderer<ListView, AListView>, SwipeRefreshLayout.IOnRefreshListener { ListViewAdapter _adapter; + bool _disposed; IVisualElementRenderer _headerRenderer; IVisualElementRenderer _footerRenderer; Container _headerView; @@ -25,6 +26,12 @@ namespace Xamarin.Forms.Platform.Android IListViewController Controller => Element; ITemplatedItemsView<Cell> TemplatedItemsView => Element; + public ListViewRenderer(Context context) : base(context) + { + AutoPackage = false; + } + + [Obsolete("This constructor is obsolete as of version 3.0. Please use ListViewRenderer(Context) instead.")] public ListViewRenderer() { AutoPackage = false; @@ -38,29 +45,33 @@ namespace Xamarin.Forms.Platform.Android protected override void Dispose(bool disposing) { - if (disposing) + if (_disposed) { - if (_headerView == null) - return; + return; + } + + _disposed = true; + if (disposing) + { if (_headerRenderer != null) { - (_headerRenderer.View as ViewGroup)?.RemoveAllViews(); + ClearRenderer(_headerRenderer.View); _headerRenderer.Dispose(); _headerRenderer = null; } + _headerView?.Dispose(); + _headerView = null; + if (_footerRenderer != null) { - (_footerRenderer.View as ViewGroup)?.RemoveAllViews(); + ClearRenderer(_footerRenderer.View); _footerRenderer.Dispose(); _footerRenderer = null; } - _headerView.Dispose(); - _headerView = null; - - _footerView.Dispose(); + _footerView?.Dispose(); _footerView = null; if (_adapter != null) @@ -141,7 +152,7 @@ namespace Xamarin.Forms.Platform.Android nativeListView.Focusable = false; nativeListView.DescendantFocusability = DescendantFocusability.AfterDescendants; nativeListView.OnFocusChangeListener = this; - nativeListView.Adapter = _adapter = e.NewElement.IsGroupingEnabled && e.NewElement.OnThisPlatform ().IsFastScrollEnabled () ? new GroupedListViewAdapter (Context, nativeListView, e.NewElement) : new ListViewAdapter(Context, nativeListView, e.NewElement); + nativeListView.Adapter = _adapter = e.NewElement.IsGroupingEnabled && e.NewElement.OnThisPlatform().IsFastScrollEnabled() ? new GroupedListViewAdapter(Context, nativeListView, e.NewElement) : new ListViewAdapter(Context, nativeListView, e.NewElement); _adapter.HeaderView = _headerView; _adapter.FooterView = _footerView; _adapter.IsAttachedToWindow = _isAttached; @@ -151,7 +162,7 @@ namespace Xamarin.Forms.Platform.Android UpdateIsSwipeToRefreshEnabled(); UpdateFastScrollEnabled(); - + } } @@ -272,15 +283,38 @@ namespace Xamarin.Forms.Platform.Android Control.SetSelectionFromTop(realPositionWithHeader, y); } + void ClearRenderer(AView renderedView) + { + var element = (renderedView as IVisualElementRenderer)?.Element; + var view = element as View; + if (view != null) + { + var renderer = Platform.GetRenderer(view); + if (renderer == renderedView) + element.ClearValue(Platform.RendererProperty); + renderer?.Dispose(); + renderer = null; + } + var layout = view as IVisualElementRenderer; + layout?.Dispose(); + layout = null; + } + void UpdateFooter() { var footer = (VisualElement)Controller.FooterElement; - if (_footerRenderer != null && (footer == null || Registrar.Registered.GetHandlerType(footer.GetType()) != _footerRenderer.GetType())) + if (_footerRenderer != null) { - if (_footerView != null) - _footerView.Child = null; - _footerRenderer.Dispose(); - _footerRenderer = null; + var reflectableType = _footerRenderer as System.Reflection.IReflectableType; + var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : _footerRenderer.GetType(); + if (footer == null || Registrar.Registered.GetHandlerTypeForObject(footer) != rendererType) + { + if (_footerView != null) + _footerView.Child = null; + ClearRenderer(_footerRenderer.View); + _footerRenderer.Dispose(); + _footerRenderer = null; + } } if (footer == null) @@ -290,7 +324,7 @@ namespace Xamarin.Forms.Platform.Android _footerRenderer.SetElement(footer); else { - _footerRenderer = Platform.CreateRenderer(footer); + _footerRenderer = Platform.CreateRenderer(footer, Context); if (_footerView != null) _footerView.Child = _footerRenderer; } @@ -301,12 +335,18 @@ namespace Xamarin.Forms.Platform.Android void UpdateHeader() { var header = (VisualElement)Controller.HeaderElement; - if (_headerRenderer != null && (header == null || Registrar.Registered.GetHandlerType(header.GetType()) != _headerRenderer.GetType())) + if (_headerRenderer != null) { - if (_headerView != null) - _headerView.Child = null; - _headerRenderer.Dispose(); - _headerRenderer = null; + var reflectableType = _headerRenderer as System.Reflection.IReflectableType; + var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : _headerRenderer.GetType(); + if (header == null || Registrar.Registered.GetHandlerTypeForObject(header) != rendererType) + { + if (_headerView != null) + _headerView.Child = null; + ClearRenderer(_headerRenderer.View); + _headerRenderer.Dispose(); + _headerRenderer = null; + } } if (header == null) @@ -316,7 +356,7 @@ namespace Xamarin.Forms.Platform.Android _headerRenderer.SetElement(header); else { - _headerRenderer = Platform.CreateRenderer(header); + _headerRenderer = Platform.CreateRenderer(header, Context); if (_headerView != null) _headerView.Child = _headerRenderer; } @@ -350,8 +390,9 @@ namespace Xamarin.Forms.Platform.Android void UpdateFastScrollEnabled() { - if (Control != null) { - Control.FastScrollEnabled = Element.OnThisPlatform ().IsFastScrollEnabled (); + if (Control != null) + { + Control.FastScrollEnabled = Element.OnThisPlatform().IsFastScrollEnabled(); } } |