From a8d4c8d799ee1abf5338028361b0855745ebae47 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Thu, 13 Sep 2018 14:24:13 +0800 Subject: [PATCH] Add a new Disposable Extention. --- src/Avalonia.Animation/Animator`1.cs | 11 +++-- .../Reactive/DisposeOnNextObservable.cs | 40 +++++++++++++++++++ src/Avalonia.Base/Reactive/ObservableEx.cs | 17 +++++++- 3 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 src/Avalonia.Base/Reactive/DisposeOnNextObservable.cs diff --git a/src/Avalonia.Animation/Animator`1.cs b/src/Avalonia.Animation/Animator`1.cs index e4af0f356d..888450e7f0 100644 --- a/src/Avalonia.Animation/Animator`1.cs +++ b/src/Avalonia.Animation/Animator`1.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reactive.Disposables; using System.Reactive.Linq; using Avalonia.Animation.Utils; using Avalonia.Collections; using Avalonia.Data; +using Avalonia.Reactive; + namespace Avalonia.Animation { @@ -38,10 +41,10 @@ namespace Avalonia.Animation VerifyConvertKeyFrames(); return match.DistinctUntilChanged() - .Select(x => x ? RunKeyFrames(animation, control, onComplete) : null) - .Buffer(2, 1) - .Where(x => x.Count > 1) - .Subscribe(x => x[0]?.Dispose()); + .ObserveOn(Avalonia.Threading.AvaloniaScheduler.Instance) + .Select(x => x ? RunKeyFrames(animation, control, onComplete) : Disposable.Empty) + .DisposeCurrentOnNext() + .Subscribe(); } /// diff --git a/src/Avalonia.Base/Reactive/DisposeOnNextObservable.cs b/src/Avalonia.Base/Reactive/DisposeOnNextObservable.cs new file mode 100644 index 0000000000..8650fe5400 --- /dev/null +++ b/src/Avalonia.Base/Reactive/DisposeOnNextObservable.cs @@ -0,0 +1,40 @@ +using System; +using Avalonia.Threading; + +namespace Avalonia.Reactive +{ + public class DisposeOnNextObservable : LightweightObservableBase, IObserver where T : IDisposable + { + private IDisposable lastValue; + + private void ValueNext(T value) + { + this.PublishNext(value); + lastValue?.Dispose(); + lastValue = value; + } + + public void OnCompleted() + { + this.PublishCompleted(); + } + + public void OnError(Exception error) + { + this.PublishError(error); + } + + void IObserver.OnNext(T value) + { + ValueNext(value); + } + + protected override void Initialize() + { + } + + protected override void Deinitialize() + { + } + } +} \ No newline at end of file diff --git a/src/Avalonia.Base/Reactive/ObservableEx.cs b/src/Avalonia.Base/Reactive/ObservableEx.cs index 5b2a39d5ff..dc3be36015 100644 --- a/src/Avalonia.Base/Reactive/ObservableEx.cs +++ b/src/Avalonia.Base/Reactive/ObservableEx.cs @@ -22,6 +22,20 @@ namespace Avalonia.Reactive return new SingleValueImpl(value); } + /// + /// Disposes the current and saves the next. + /// + /// The type of the value. + /// The source . + /// The observable. + public static IObservable DisposeCurrentOnNext(this IObservable observable) + where T : IDisposable + { + var subject = new DisposeOnNextObservable(); + observable.Subscribe(subject); + return subject; + } + private class SingleValueImpl : IObservable { private T _value; @@ -30,7 +44,6 @@ namespace Avalonia.Reactive { _value = value; } - public IDisposable Subscribe(IObserver observer) { observer.OnNext(_value); @@ -38,4 +51,4 @@ namespace Avalonia.Reactive } } } -} +} \ No newline at end of file