我目前有一个View(Android Fragment)和一个相应的ViewModel。我现在想在ViewModel中引发一个View可以订阅的事件。
归档此内容的最佳方式是什么?我听说过常规的C#事件(委托)会导致内存泄漏吗?这是WeakSubscribe功能的原因吗?如何将其绑定到事件?
答案 0 :(得分:12)
为防止视图中的内存泄漏,您订阅的每个事件都需要取消订阅,无论是使用WeakSubscribe
还是照常订阅活动。
常见的情况是订阅:
OnResume()
ViewWillAppear()
然后将订阅部署在:
OnPause()
ViewWillDisappear()
如果您想“监听”ViewModel属性更改,WeakSubscribe
会派上用场:
private IDisposable _selectedItemToken;
_selectedItemToken = ViewModel.WeakSubscribe(() =>
ViewModel.SelectedItem, (sender, eventArgs) => {
// do something
});
请注意
WeakSubscribe()
返回的MvxWeakEventSubscription也是IDisposable
。您需要在视图中保存对该订阅的引用,并在不再需要该视图时将其处理。 保留该引用有两个原因:
- 您可以稍后处理
- 如果你不保留它,你的lambda事件处理程序可能并不总是有用
醇>
稍后......
_selectedItemToken?.Dispose();
如果您只需要在ViewModel中订阅其他类型的事件(而不是属性更改),则实际上您不需要WeakSubscribe
。您可以像对待任何对象一样向ViewModel添加事件侦听器。
ViewModel.AnEvent += YourDelegate;
稍后......
ViewModel.AnEvent -= YourDelegate;
别忘了最后一步。这将防止内存泄漏。正如我所说,Android
OnPause()
和iOSViewWillDisappear()
是做这件事的好地方。
这样,当视图被处理时,你的ViewModel就不会卡在内存中,因此你的视图可以被正确地垃圾收集。
答案 1 :(得分:1)
如果您订阅临时对象中的事件并且在释放临时对象之前没有取消订阅,则可以创建泄漏。在您的情况下很少有机会,因为视图模型最有可能只创建一次。
由于您使用的是mvvm,因此您可以在MvvmLight或MvvmCross等流行的mvvm框架中找到实现的Messenger。这为您提供了真正的分离事件,因为您只需要知道消息的格式,而不需要知道有关发送者的任何信息(在您的情况下是ViewModel)。使用messenger,您只能订阅消息类型,发件人可以在应用程序的任何位置。