Using Mvx Messenger for loosely coupled communication

http://deapsquatter.blogspot.ie/2013/04/using-mvx-messenger-for-loosely-coupled.html

Tuesday, April 23, 2013

Using Mvx Messenger for loosely coupled communication

A ViewModel often needs to know of some status change in a service class. For instance you may have  a network connection that you keep open to your platform. The ViewModel may want to know when this connection goes up and down.

.NET Events

When your ViewModel is created it subscribes to the event you interested in monitoring.

12

var connection = Mvx.Resolve<INetworkConnection>();

connection.OnChange += () => RaisePropertyChanged(“IsConnecting”)

view rawgistfile1.cs hosted with ❤ by GitHub

This works just fine. When the connection state changes you get notified and raise the fact that the IsConnecting property on your ViewModel has changed. Any UI that is bound to this property can update accordingly.

The problem with this approach is that the INetworkConnection outlives the ViewModel. Whats supposed to happen is when the View leaves the screen it gets garbage collected along with the ViewModel it owns. Now the INetworkConnection has a reference to the ViewModel (created by the event subscription) effectively preventing the ViewModel from getting GC’d. Of course we can make sure we unsubscribe from the event at some point but this has its caveats and becomes messy. We need a better way…

Enter the MvxMessenger

OK so these Message Aggregators have been around for a while. I’ve used TinyMessenger in the past when using V2 of MvvmCross. V3 introduces an MvxMessenger in the form of a Plugin. To get started make sure you register the plugin in your Setup class.

12345

public override void LoadPlugins (IMvxPluginManager pluginManager)

{

base.LoadPlugins (pluginManager);

pluginManager.EnsurePluginLoaded<Cirrious.MvvmCross.Plugins.Messenger.PluginLoader> ();

}

view rawgistfile1.cs hosted with ❤ by GitHub

In this example my ViewModel registers interest in a message inside its constructor.

1234

public HomeVM ()

{

token = MessageHub.Subscribe<CoreStatusMessage> ((d) => CoreStatusChanged(d.CoreStatus));

}

view rawgistfile1.cs hosted with ❤ by GitHub

MessageHub is a property on my ViewModel base class that just returns an instance of the IMvxMessenger plugin we registered in the beginning. Something worth noting is that the token returned is stored in a field within the ViewModel. MvxMessenger uses a WeakReference to the Action<TMessage> when you subscribe. If you don’t hold on to the token the reference gets lost and you wont receive your message. Something else to consider is the thread where your Action delegate (the one you passed to IMvxMessenger.Subscribe) gets called. In this example it will be called on whatever thread the INetworkConnection calls the IMvxMessenger.Publish() method on. Checkout IMvxMessenger.SubscribeOnMainThread which is especially important if your Action code calls into the UI. Using RaisePropertyChanged in your Action code is a prime example.

The Publish() method (already mentioned above) is used to send a message to subscribers. In this example its called by the INetworkConnection when its state changes. CoreStatusMessage is a MvxMessage that you can customise as you please.

12345

void ConnectionChanged (CoreStatusType coreStatus)

{

IMvxMessenger messenger = Mvx.Resolve(IMvxMessenger);

messenger.Publish (new CoreStatusMessage(sender, coreStatus));

}

view rawgistfile1.cs hosted with ❤ by GitHub

Conclusion

The great thing about this is you don’t have to be concerned with holding on to objects and causing memory leaks. Consider using this instead of regular events in your MvvmCross app’s. Especially where short lived Views need event’s from some of your long living service classes.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s