summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/Renderers
diff options
context:
space:
mode:
authorSamantha Houts <samhouts@users.noreply.github.com>2017-10-18 14:28:18 -0700
committerRui Marinho <me@ruimarinho.net>2017-10-18 22:46:09 +0100
commit3b9712aaf5d0e8932d1e30facc9ec842a43f6860 (patch)
tree71b91ca39de0c0fc9ad3e5cebe42755c8d3b9e94 /Xamarin.Forms.Platform.Android/Renderers
parent0927f1e6889a2f92864c8bfc384cfd4c3fa9c7ed (diff)
downloadxamarin-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/Renderers')
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs91
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();
}
}