Skip to content

Commit f8171b4

Browse files
hartezrmarinho
authored andcommitted
Occasionally clean up WeakReferences in Styles whose targets have been collected (#8124)
1 parent 0fe1b71 commit f8171b4

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

Xamarin.Forms.Core/Interactivity/AttachedCollection.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ internal class AttachedCollection<T> : ObservableCollection<T>, ICollection<T>,
88
{
99
readonly List<WeakReference> _associatedObjects = new List<WeakReference>();
1010

11+
const int CleanupTrigger = 128;
12+
int _cleanupThreshold = CleanupTrigger;
13+
1114
public AttachedCollection()
1215
{
1316
}
@@ -64,6 +67,7 @@ protected virtual void OnAttachedTo(BindableObject bindable)
6467
lock (_associatedObjects)
6568
{
6669
_associatedObjects.Add(new WeakReference(bindable));
70+
CleanUpWeakReferences();
6771
}
6872
foreach (T item in this)
6973
item.AttachTo(bindable);
@@ -123,5 +127,16 @@ protected override void SetItem(int index, T item)
123127
item.AttachTo(bindable);
124128
}
125129
}
130+
131+
void CleanUpWeakReferences()
132+
{
133+
if (_associatedObjects.Count < _cleanupThreshold)
134+
{
135+
return;
136+
}
137+
138+
_associatedObjects.RemoveAll(t => !t.IsAlive);
139+
_cleanupThreshold = _associatedObjects.Count + CleanupTrigger;
140+
}
126141
}
127142
}

Xamarin.Forms.Core/Style.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ public sealed class Style : IStyle
1010
{
1111
internal const string StyleClassPrefix = "Xamarin.Forms.StyleClass.";
1212

13+
const int CleanupTrigger = 128;
14+
int _cleanupThreshold = CleanupTrigger;
15+
1316
readonly BindableProperty _basedOnResourceProperty = BindableProperty.CreateAttached("BasedOnResource", typeof(Style), typeof(Style), default(Style),
1417
propertyChanged: OnBasedOnResourceChanged);
1518

@@ -93,6 +96,8 @@ void IStyle.Apply(BindableObject bindable)
9396
if (BaseResourceKey != null)
9497
bindable.SetDynamicResource(_basedOnResourceProperty, BaseResourceKey);
9598
ApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
99+
100+
CleanUpWeakReferences();
96101
}
97102

98103
public Type TargetType { get; }
@@ -178,5 +183,16 @@ bool ValidateBasedOn(Style value)
178183
return true;
179184
return value.TargetType.IsAssignableFrom(TargetType);
180185
}
186+
187+
void CleanUpWeakReferences()
188+
{
189+
if (_targets.Count < _cleanupThreshold)
190+
{
191+
return;
192+
}
193+
194+
_targets.RemoveAll(t => !t.TryGetTarget(out _));
195+
_cleanupThreshold = _targets.Count + CleanupTrigger;
196+
}
181197
}
182198
}

0 commit comments

Comments
 (0)