MvvmCross:在 ViewModel 中引发事件的最佳方式?
MvvmCross: Best way to raise event in ViewModel?
我目前有一个视图(Android 片段)和一个对应的 ViewModel。我现在想在视图可以订阅的视图模型中引发一个事件。
存档的最佳方式是什么?我听说常规 C# 事件(委托)会导致内存泄漏?这是WeakSubscribe函数的原因吗?如何绑定到事件?
如果您订阅临时对象中的事件并且在释放临时对象之前不取消订阅,则可能会造成泄漏。在您的情况下,这种情况的可能性很小,因为视图模型很可能只会创建一次。
由于您使用的是 mvvm,事件的替代方法是 Messengers,您可以在 MvvmLight 或 MvvmCross 等流行的 mvvm 框架中找到它。这为您提供了真正解耦的事件,因为您只需要知道消息的格式而无需了解有关发件人的任何信息(在您的情况下是 ViewModel)。使用 Messenger,您只需订阅一种消息类型,发件人可以在应用程序的任何位置。
为了防止您的视图内存泄漏,您订阅的每个事件都需要取消订阅,无论是使用 WeakSubscribe
还是照常订阅事件。
一个常见的场景是订阅:
- Android
OnResume()
- iOS
ViewWillAppear()
然后处理订阅:
- Android
OnPause()
- iOS
ViewWillDisappear()
弱订阅
如果你想"listen" for ViewModel 属性改变,WeakSubscribe
就派上用场了:
private IDisposable _selectedItemToken;
_selectedItemToken = ViewModel.WeakSubscribe(() =>
ViewModel.SelectedItem, (sender, eventArgs) => {
// do something
});
Just notice that WeakSubscribe()
returns an MvxWeakEventSubscription that is also IDisposable
. You need to save a reference to that subscription in your view and dispose it when thew view is no longer needed.
There are two reasons to keep that reference:
- You can dispose it later
- If you don´t keep it, your lambda event handler may not always work
稍后...
_selectedItemToken?.Dispose();
正常事件订阅
如果您只需要在您的 ViewModel 中订阅另一种事件(而不是 属性 更改),您实际上并不需要 WeakSubscribe
。您可以只向 ViewModel 添加一个事件侦听器,就像您对任何对象所做的那样。
ViewModel.AnEvent += YourDelegate;
稍后...
ViewModel.AnEvent -= YourDelegate;
Don´t forget the last step. That will prevent memory leaks. As I said, Android OnPause()
and iOS ViewWillDisappear()
are good places to do it.
这样,当视图被释放时,您的 ViewModel 就不会卡在内存中,因此您的视图可以正确地被垃圾回收。
我目前有一个视图(Android 片段)和一个对应的 ViewModel。我现在想在视图可以订阅的视图模型中引发一个事件。
存档的最佳方式是什么?我听说常规 C# 事件(委托)会导致内存泄漏?这是WeakSubscribe函数的原因吗?如何绑定到事件?
如果您订阅临时对象中的事件并且在释放临时对象之前不取消订阅,则可能会造成泄漏。在您的情况下,这种情况的可能性很小,因为视图模型很可能只会创建一次。
由于您使用的是 mvvm,事件的替代方法是 Messengers,您可以在 MvvmLight 或 MvvmCross 等流行的 mvvm 框架中找到它。这为您提供了真正解耦的事件,因为您只需要知道消息的格式而无需了解有关发件人的任何信息(在您的情况下是 ViewModel)。使用 Messenger,您只需订阅一种消息类型,发件人可以在应用程序的任何位置。
为了防止您的视图内存泄漏,您订阅的每个事件都需要取消订阅,无论是使用 WeakSubscribe
还是照常订阅事件。
一个常见的场景是订阅:
- Android
OnResume()
- iOS
ViewWillAppear()
然后处理订阅:
- Android
OnPause()
- iOS
ViewWillDisappear()
弱订阅
如果你想"listen" for ViewModel 属性改变,WeakSubscribe
就派上用场了:
private IDisposable _selectedItemToken;
_selectedItemToken = ViewModel.WeakSubscribe(() =>
ViewModel.SelectedItem, (sender, eventArgs) => {
// do something
});
Just notice that
WeakSubscribe()
returns an MvxWeakEventSubscription that is alsoIDisposable
. You need to save a reference to that subscription in your view and dispose it when thew view is no longer needed. There are two reasons to keep that reference:
- You can dispose it later
- If you don´t keep it, your lambda event handler may not always work
稍后...
_selectedItemToken?.Dispose();
正常事件订阅
如果您只需要在您的 ViewModel 中订阅另一种事件(而不是 属性 更改),您实际上并不需要 WeakSubscribe
。您可以只向 ViewModel 添加一个事件侦听器,就像您对任何对象所做的那样。
ViewModel.AnEvent += YourDelegate;
稍后...
ViewModel.AnEvent -= YourDelegate;
Don´t forget the last step. That will prevent memory leaks. As I said, Android
OnPause()
and iOSViewWillDisappear()
are good places to do it.
这样,当视图被释放时,您的 ViewModel 就不会卡在内存中,因此您的视图可以正确地被垃圾回收。