I currently have a View (Android Fragment) and a coresponding ViewModel. I now want to raise an event in the ViewModel which the View can subscribe to.
What's the best way to archive this? I heard a regular C# event (delegate) can lead to memory leaks? Is this the reason for the WeakSubscribe function? How to bind it to an event?
To prevent memory leaks in your views, every event you subscribed to needs to be unsubscribed from, either way using WeakSubscribe
or subscribing to events as usual.
A common scenario would be subscribing on:
OnResume()
ViewWillAppear()
then dispose the subscription on:
OnPause()
ViewWillDisappear()
If you want to "listen" for ViewModel property changes, WeakSubscribe
comes in handy:
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
Later on...
_selectedItemToken?.Dispose();
If you just need to subscribe to another kind of event (not property changes) in your ViewModel, you don´t actually need WeakSubscribe
. You can just add an event listener to the ViewModel, as you would do with any object.
ViewModel.AnEvent += YourDelegate;
Later on...
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.
That way your ViewModel won´t be stuck in memory when the view is disposed thus your view can be garbage collected correctly.
You can create a leak if you subscribe to an event in a temporary object and don't unsubscribe before releasing the temporary object. Little chance for that in your case as the view model most likely will be created only once.
Since you are using mvvm, an alternative to events are Messengers which you can find implemented in popular mvvm-frameworks like MvvmLight or MvvmCross. This gives you truly decoupled events as you only need to know the format of the message and don't need to know anything about the sender (which in your case is the ViewModel). With messenger you only subscribe to a message-type and the sender can be anywhere in the app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With