我已经从博客中查看了ReactiveUi的示例,我想知道ReactiveUI是否在下面有某种订阅管理工具,或者是忽略了他们可能泄漏订阅这一事实的例子?
每当我在ReactiveUi中调用一个导致IDisposable
的方法时,我是否需要保留该引用并自行跟踪它?这也意味着我的ViewModel需要是一次性的,这似乎很难,因为我们不知道什么时候连接的“视图”消失了(即如果我的ViewModel反映了数据网格中的项目),所以似乎没有合适的叫做出售的地方。
答案 0 :(得分:14)
您还必须记住,Rx和ReactiveUI返回的IDisposable与非托管内存无关 - 它只是简单的.NET对象,仍由垃圾收集器引用。
您在ReactiveObjects的构造函数中创建的大多数订阅都将绑定到宿主对象的生命周期 - 因此当它超出范围并受GC影响时,所有订阅也将如此,CLR将检测到循环引用,只是核实一切。
正如Enigmativity所提到的,一个棘手的问题是当您使用FromEventPattern将订阅的生命周期(可能是ViewModel)与WPF对象的生命周期联系起来时。但是,我认为如果你经常在ReactiveUI中使用FromEventPattern,那么你肯定是在做错了。
RxUI是关于ViewModels的,而ViewModels都是关于命令和属性(以及如何相互关联属性),因此您可以测试<用户体验的行为与其视觉效果分开。
答案 1 :(得分:11)
如果您需要从观察中取消订阅早期,则只需要保留对订阅返回的IDisposable
的引用。当观察者通过Dispose
或OnCompleted
消息终止时,Observable会自然致电OnError
。
但是,当您拥有无限可观察订阅(即FromEventPattern
)时,您确实需要保留引用,但这与在关闭表单/视图之前需要删除事件处理程序完全相同。
答案 2 :(得分:2)
为了安全起见,我将从现在开始使用这种模式。我可能会 通过扩展方法修改工作,但原则是合理的。确定你 不要泄漏您想要删除的订阅
class Mesh2D{
public Mesh2D()
{
DisposeOnUnload(CreateBindings());
}
// Register all disposables for disposal on
// UIElement.Unload event. This should be
// moved to an extension method.
void DisposeOnUnload(IEnumerable<IDisposable> disposables)
{
var d = new CompositeDisposable(disposables);
var d2 = this.UnloadedObserver()
.Subscribe(e => d.Dispose());
var d3 = this.Dispatcher.ShutdownStartedObserver()
.Subscribe(e => d.Dispose());
d.Add(d2);
d.Add(d3);
}
// Where your bindings are simply yielded and
// they are removed on Unload magically
IEnumerable<IDisposable> CreateBindings()
{
// When the size changes we need to update all the transforms on
// the markers to reposition them.
yield return this.SizeChangedObserver()
.Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler)
.Subscribe(eventArgs => this.ResetImageSource());
// If the points change or the viewport changes
yield return this.WhenAny(t => t.Mesh, t => t.Viewport, (x, t) => x.Value)
.Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler)
.Subscribe(t => this.UpdateMeshChanged());
}
}
注意我正在自动生成包装RX FromEventPattern 扩展方法,所以我得到SizeChangedObserver()和UnloadedObserver() 免费而不是难以记住的FromEventPattern格式。
包装代码就是这样生成的
public static IObservable<EventPattern<RoutedEventArgs>> UnloadedObserver(this FrameworkElement This){
return Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(h => This.Unloaded += h, h => This.Unloaded -= h);
}
上述模式可能用于取消绑定IDisposable 查看模型。