Browse Source

Implement custom observable for classes.

Use a custom `ClassObserver` for observing changes to a control's classes. This saves shaves off about 15% memory use in ControlCatalog after cyling through all tabs.
pull/1690/head
Steven Kirk 9 years ago
committed by Steven Kirk
parent
commit
d3a0507f35
  1. 70
      src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs

70
src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs

@ -5,9 +5,11 @@ using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reflection;
using System.Text;
using Avalonia.Collections;
namespace Avalonia.Styling
{
@ -122,14 +124,7 @@ namespace Avalonia.Styling
{
if (subscribe)
{
var observable = Observable.FromEventPattern<
NotifyCollectionChangedEventHandler,
NotifyCollectionChangedEventArgs>(
x => control.Classes.CollectionChanged += x,
x => control.Classes.CollectionChanged -= x)
.StartWith((EventPattern<NotifyCollectionChangedEventArgs>)null)
.Select(_ => Matches(control.Classes))
.DistinctUntilChanged();
var observable = new ClassObserver(control.Classes, _classes.Value);
return new SelectorMatch(observable);
}
else
@ -204,5 +199,64 @@ namespace Avalonia.Styling
return builder.ToString();
}
private class ClassObserver : IObservable<bool>
{
readonly IList<string> _match;
readonly List<IObserver<bool>> _observers = new List<IObserver<bool>>();
IAvaloniaReadOnlyList<string> _classes;
public ClassObserver(IAvaloniaReadOnlyList<string> classes, IList<string> match)
{
_classes = classes;
_match = match;
}
public IDisposable Subscribe(IObserver<bool> observer)
{
if (_observers.Count == 0)
{
_classes.CollectionChanged += ClassesChanged;
}
_observers.Add(observer);
observer.OnNext(GetResult());
return Disposable.Create(() =>
{
_observers.Remove(observer);
if (_observers.Count == 0)
{
_classes.CollectionChanged -= ClassesChanged;
}
});
}
private void ClassesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action != NotifyCollectionChangedAction.Move)
{
foreach (var observer in _observers)
{
observer.OnNext(GetResult());
}
}
}
private bool GetResult()
{
int remaining = _match.Count;
foreach (var c in _classes)
{
if (_match.Contains(c))
{
--remaining;
}
}
return remaining == 0;
}
}
}
}

Loading…
Cancel
Save