Skip to content

Commit

Permalink
Occasionally clean up WeakReferences in Styles whose targets have bee…
Browse files Browse the repository at this point in the history
…n collected (#8124)
  • Loading branch information
hartez authored and rmarinho committed Oct 24, 2019
1 parent 0fe1b71 commit f8171b4
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
15 changes: 15 additions & 0 deletions Xamarin.Forms.Core/Interactivity/AttachedCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ internal class AttachedCollection<T> : ObservableCollection<T>, ICollection<T>,
{
readonly List<WeakReference> _associatedObjects = new List<WeakReference>();

const int CleanupTrigger = 128;
int _cleanupThreshold = CleanupTrigger;

public AttachedCollection()
{
}
Expand Down Expand Up @@ -64,6 +67,7 @@ protected virtual void OnAttachedTo(BindableObject bindable)
lock (_associatedObjects)
{
_associatedObjects.Add(new WeakReference(bindable));
CleanUpWeakReferences();
}
foreach (T item in this)
item.AttachTo(bindable);
Expand Down Expand Up @@ -123,5 +127,16 @@ protected override void SetItem(int index, T item)
item.AttachTo(bindable);
}
}

void CleanUpWeakReferences()
{
if (_associatedObjects.Count < _cleanupThreshold)
{
return;
}

_associatedObjects.RemoveAll(t => !t.IsAlive);
_cleanupThreshold = _associatedObjects.Count + CleanupTrigger;
}
}
}
16 changes: 16 additions & 0 deletions Xamarin.Forms.Core/Style.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ public sealed class Style : IStyle
{
internal const string StyleClassPrefix = "Xamarin.Forms.StyleClass.";

const int CleanupTrigger = 128;
int _cleanupThreshold = CleanupTrigger;

readonly BindableProperty _basedOnResourceProperty = BindableProperty.CreateAttached("BasedOnResource", typeof(Style), typeof(Style), default(Style),
propertyChanged: OnBasedOnResourceChanged);

Expand Down Expand Up @@ -93,6 +96,8 @@ void IStyle.Apply(BindableObject bindable)
if (BaseResourceKey != null)
bindable.SetDynamicResource(_basedOnResourceProperty, BaseResourceKey);
ApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));

CleanUpWeakReferences();
}

public Type TargetType { get; }
Expand Down Expand Up @@ -178,5 +183,16 @@ bool ValidateBasedOn(Style value)
return true;
return value.TargetType.IsAssignableFrom(TargetType);
}

void CleanUpWeakReferences()
{
if (_targets.Count < _cleanupThreshold)
{
return;
}

_targets.RemoveAll(t => !t.TryGetTarget(out _));
_cleanupThreshold = _targets.Count + CleanupTrigger;
}
}
}

0 comments on commit f8171b4

Please sign in to comment.