MvvmCross:在ViewModel中引发事件的最佳方式

本文关键字:事件 最佳 方式 ViewModel MvvmCross | 更新日期: 2023-09-27 18:05:39

我目前有一个视图(Android Fragment)和一个相应的ViewModel。现在我想在ViewModel中引发一个事件,View可以订阅这个事件。

最好的存档方式是什么?我听说一个常规的c#事件(委托)会导致内存泄漏?这就是使用WeakSubscribe函数的原因吗?如何将其绑定到事件?

MvvmCross:在ViewModel中引发事件的最佳方式

为了防止视图中的内存泄漏,您订阅的每个事件都需要取消订阅,无论是使用WeakSubscribe还是像往常一样订阅事件。

一个常见的场景是订阅:

  • Android OnResume()
  • iOS ViewWillAppear()

则在

上解除订阅
  • Android OnPause()
  • iOS ViewWillDisappear()

WeakSubscribe

如果你想"监听"ViewModel属性的变化,WeakSubscribe就派上用场了:

private IDisposable _selectedItemToken;
_selectedItemToken = ViewModel.WeakSubscribe(() => 
    ViewModel.SelectedItem, (sender, eventArgs) => {
        // do something
});

请注意,WeakSubscribe()返回一个MvxWeakEventSubscription,也是IDisposable。您需要在视图中保存对该订阅的引用,并在不再需要该视图时处理它。保留该引用有两个原因:

  1. 你可以稍后处理
  2. 如果你不保留它,你的lambda事件处理程序可能不总是工作

后来…

_selectedItemToken?.Dispose();

正常事件订阅

如果您只需要订阅ViewModel中的另一种事件(而不是属性更改),则实际上不需要WeakSubscribe。您可以向ViewModel添加一个事件监听器,就像您对任何对象所做的那样。

ViewModel.AnEvent += YourDelegate;

后来…

ViewModel.AnEvent -= YourDelegate;

不要忘记最后一步。这将防止内存泄漏。就像我说的,Android OnPause()和iOS ViewWillDisappear()是做这件事的好地方。

这样,当视图被处置时,您的ViewModel就不会卡在内存中,因此您的视图可以正确地进行垃圾收集。

如果您订阅了临时对象中的事件,并且在释放临时对象之前没有取消订阅,则可能会造成泄漏。在您的情况下,这种可能性很小,因为视图模型很可能只创建一次。

因为你正在使用mvvm,事件的替代方案是信使,你可以在流行的mvvm框架中找到实现,如MvvmLight或MvvmCross。这为您提供了真正解耦的事件,因为您只需要知道消息的格式,而不需要知道有关发送方的任何信息(在您的示例中是ViewModel)。使用messenger,你只能订阅一个消息类型,发送者可以在应用程序的任何地方。