From 7d1b7593a5572bbc2b74ac3e55c42065a9ba4852 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 2 Aug 2018 15:31:34 -0500 Subject: [PATCH] Dispose subscriptions on completed code-behind run of animation. --- src/Avalonia.Animation/Animation.cs | 39 +++++++++++++---------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs index c228a49ec7..56bc667f8a 100644 --- a/src/Avalonia.Animation/Animation.cs +++ b/src/Avalonia.Animation/Animation.cs @@ -12,13 +12,14 @@ using System.Reflection; using System.Linq; using System.Threading.Tasks; using System.Reactive.Linq; +using System.Reactive.Disposables; namespace Avalonia.Animation { /// /// Tracks the progress of an animation. /// - public class Animation : AvaloniaList, IDisposable, IAnimation + public class Animation : AvaloniaList, IAnimation { private readonly static List<(Func Condition, Type Animator)> Animators = new List<(Func, Type)> { @@ -43,7 +44,6 @@ namespace Avalonia.Animation return null; } - private List _subscription = new List(); public AvaloniaList _animators { get; set; } = new AvaloniaList(); /// @@ -76,10 +76,11 @@ namespace Avalonia.Animation /// public Easing Easing { get; set; } = new LinearEasing(); - private IList InterpretKeyframes(Animatable control) + private (IList Animators, IList subscriptions) InterpretKeyframes(Animatable control) { var handlerList = new List<(Type type, AvaloniaProperty property)>(); var animatorKeyFrames = new List(); + var subscriptions = new List(); foreach (var keyframe in this) { @@ -104,7 +105,7 @@ namespace Avalonia.Animation var newKF = new AnimatorKeyFrame(handler, cue); - _subscription.Add(newKF.BindSetter(setter, control)); + subscriptions.Add(newKF.BindSetter(setter, control)); animatorKeyFrames.Add(newKF); } @@ -126,32 +127,21 @@ namespace Avalonia.Animation animator.Add(keyframe); } - return newAnimatorInstances; - } - - /// - /// Cancels the animation. - /// - public void Dispose() - { - foreach (var sub in _subscription) - { - sub.Dispose(); - } + return (newAnimatorInstances, subscriptions); } /// public IDisposable Apply(Animatable control, IObservable match, Action onComplete) { - var animators = InterpretKeyframes(control); + var (animators, subscriptions) = InterpretKeyframes(control); if (animators.Count == 1) { - _subscription.Add(animators[0].Apply(this, control, match, onComplete)); + subscriptions.Add(animators[0].Apply(this, control, match, onComplete)); } else { var completionTasks = onComplete != null ? new List() : null; - foreach (IAnimator animator in InterpretKeyframes(control)) + foreach (IAnimator animator in animators) { Action animatorOnComplete = null; if (onComplete != null) @@ -160,7 +150,7 @@ namespace Avalonia.Animation animatorOnComplete = () => tcs.SetResult(null); completionTasks.Add(tcs.Task); } - _subscription.Add(animator.Apply(this, control, match, animatorOnComplete)); + subscriptions.Add(animator.Apply(this, control, match, animatorOnComplete)); } if (onComplete != null) @@ -168,7 +158,7 @@ namespace Avalonia.Animation Task.WhenAll(completionTasks).ContinueWith(_ => onComplete()); } } - return this; + return new CompositeDisposable(subscriptions); } /// @@ -179,7 +169,12 @@ namespace Avalonia.Animation if (this.RepeatCount == RepeatCount.Loop) run.SetException(new InvalidOperationException("Looping animations must not use the Run method.")); - this.Apply(control, Observable.Return(true), () => run.SetResult(null)); + IDisposable subscriptions = null; + subscriptions = this.Apply(control, Observable.Return(true), () => + { + run.SetResult(null); + subscriptions.Dispose(); + }); return run.Task; }