Skip to content

Commit

Permalink
perf: Reduce allocations in BindingItem.SubscribeToPropertyChanged
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromelaban committed Jan 17, 2022
1 parent 97d5328 commit 2740c77
Showing 1 changed file with 31 additions and 33 deletions.
64 changes: 31 additions & 33 deletions src/Uno.UI/DataBinding/BindingPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -586,28 +586,7 @@ private void OnDataContextChanged()
}
}

_propertyChanged.Disposable =
SubscribeToPropertyChanged((previousValue, newValue, shouldRaiseValueChanged) =>
{
if (_isDataContextChanging && newValue is UnsetValue)
{
// We're in a "resubscribe" scenario when the DataContext is provided a new non-null value, so we don't need to
// pass through the DependencyProperty.UnsetValue.
// We simply discard this update.
return;
}
if (Next != null)
{
Next.DataContext = newValue;
}
if (shouldRaiseValueChanged && previousValue != newValue)
{
RaiseValueChanged(newValue);
}
}
);
_propertyChanged.Disposable = SubscribeToPropertyChanged();

RaiseValueChanged(Value);

Expand All @@ -628,6 +607,27 @@ private void OnDataContextChanged()
}
}

private void OnPropertyChanged(object? previousValue, object? newValue, bool shouldRaiseValueChanged)
{
if (_isDataContextChanging && newValue is UnsetValue)
{
// We're in a "resubscribe" scenario when the DataContext is provided a new non-null value, so we don't need to
// pass through the DependencyProperty.UnsetValue.
// We simply discard this update.
return;
}

if (Next != null)
{
Next.DataContext = newValue;
}

if (shouldRaiseValueChanged && previousValue != newValue)
{
RaiseValueChanged(newValue);
}
}

private void ClearCachedGetters()
{
var currentType = DataContext!.GetType();
Expand Down Expand Up @@ -801,9 +801,9 @@ private void RaiseValueChanged(object? newValue)
/// </summary>
/// <param name="action">The action to execute when new values are raised</param>
/// <returns>A disposable to be called when the subscription is disposed.</returns>
private IDisposable SubscribeToPropertyChanged(PropertyChangedHandler action)
private IDisposable SubscribeToPropertyChanged()
{
var disposables = new CompositeDisposable((_propertyChangedHandlers.Count * 3));
var disposables = new CompositeDisposable(_propertyChangedHandlers.Count);

for (var i = 0; i < _propertyChangedHandlers.Count; i++)
{
Expand All @@ -814,16 +814,11 @@ private IDisposable SubscribeToPropertyChanged(PropertyChangedHandler action)
{
var newValue = GetSourceValue();
action(previousValue, newValue, shouldRaiseValueChanged: true);
OnPropertyChanged(previousValue, newValue, shouldRaiseValueChanged: true);
previousValue = newValue;
};

Action disposeAction = () =>
{
action(previousValue, DependencyProperty.UnsetValue, shouldRaiseValueChanged: false);
};

var handlerDisposable = handler(_dataContextWeakStorage!, PropertyName, updateProperty);

if (handlerDisposable != null)
Expand All @@ -836,9 +831,12 @@ private IDisposable SubscribeToPropertyChanged(PropertyChangedHandler action)
//
// All registrations made by _propertyChangedHandlers are
// weak with regards to the delegates that are provided.
disposables.Add(() => updateProperty = null);
disposables.Add(handlerDisposable);
disposables.Add(disposeAction);
disposables.Add(() =>
{
updateProperty = null;
handlerDisposable.Dispose();
OnPropertyChanged(previousValue, DependencyProperty.UnsetValue, shouldRaiseValueChanged: false);
});
}
}

Expand Down

0 comments on commit 2740c77

Please sign in to comment.