MessagingCenter is a global event messaging system designed to allow two separate entities communicate without knowing anything about each other, besides a simple messaging contract. This architectural style of system works well for larger systems such as Amazon who use a similar event-sourced approach of micro services to implement a recommendation system, payment system, shipping system etc. These systems are distinctly separate and have teams working on each.
Mobile application development however is dealing with a much smaller system in most circumstances, with a single user interacting with a single page. To implement MessagingCenter in a mobile application is either a complete over architecture or its not being done properly.
Timing & State Issues
Timing issues are one of the largest concerns I have seen with MessagingCenter. If you load a page and OnAppearing is called and you have the possibility of a subscription to the MessagingCenter, how would you know if the OnAppearing got called first or the MessagingCenter. State validity is the main concern here as with all the following scenarios. MVVM is assumed in a few patterns.
ViewModel to Page
If you have a page binding to a ViewModel, the binding engine is there to relay information back and forth between the two entities. If you add MessagingCenter, then you add an additional path for the data to flow. If accessing a method on a control is the main concern, then expand the control to add Bindable Properties.
Page to Page
States should be managed by the Model, through the ViewModel, through the binding engine to the page. Jumping across pages can lead to immense state issues when your binding engine is competing with your subscriptions to modify page elements.
ViewModel to ViewModel
VM to VM communication is a common example of MessagingCenter usage. Communicating with an inactive VM boudn to a page that most likely isn’t showing yet is a pathway to timing and state issues.
To push data from one VM to another as you move pages in your application you can provide these mechanisms in your Navigation Service. The Navigation Service will already have a reference to your Page and ViewModel for binding and pushing purposes, why not just add a parameter to the Push command and pass that through when you have a reference to your new ViewModel.
// In your current ViewModel await _navigationService.Push(args); // In Navigation Service myPage.BindingContext = theViewModel; await _navigationPage.PushAsync(); theViewModel.OnNavigated(args);
Model to Model or Service
Models and services can talk to each other via constructor injection. If your model has a dependency on another model, then it should list it, as with services.
If you are now thinking that your Model’s have a hard dependency, this is true, but why shouldn’t they. It is obvious one depends upon the other, the MessagingCenter doesn’t alleviate the dependency, just makes it harder or you to track. You can go one step further and split the entity.
It is important that your models or services all implement an appropriate interface. With this approach you can restrict what a class does call of another and allow other classes greater API access.
Following Dependencies Not Events
Debugging code with events, especially ones tied together by magic strings, as is the case in most MessagingCenter implementations, becomes a nightmare. Following dependencies give greater assurance that operations are performed in sequence and that you can trace the code back without setting up debugging break points everywhere to trap an event.
Summary
While MessagingCenter isn’t suitable for many tasks, there is one where I have found use for it. This is with Background Processes. If you are downloading a file in the background, or performing some other intensive task, completely separate to the app, then MessagingCenter is a good way to transmit messages across two distinctly different operations. Other than this, I have found no other use for MessagingCenter.
Mobile Developer | Build Flutter
I’ve used it mainly when I’m deep in the navigation stack and I need to notify something higher up that something changed. A specific instance I had was my app was a Master-detail application with counts next to the menu items. Anytime something changed in the app, I would just send a message that the menu list needed to refresh.
Do you have any recommendations in that scenario?
Thanks for listing out your scenario. A possible other solution would be to look at having an class with the counts in them, something that holds the these states. This entity/class is then injected in the pages that update it, and also the Master page. Then when one updates the counts, binding will reflect that across anything that is bound to those properties.
Imagine having a list of bookings on 1 page, the list of bookings is cached so you don’t have to to back to the server every time. The only time you will refresh this list is when user explicitly requests or when user makes a new booking. So, the create booking view model, will send a notification via messaging center to the booking list view model so it can refresh itself and include the new booking to its list.
What do you think?
My approach to that situation would be to have the cached list of the bookings in a BookingModel that both the ViewModel’s have access to. Then when one ViewModel updates the BookingModel’s list of bookings, the other ViewModel has immediate access to them when needed. The BookingModel is a single instance shared across both ViewModels.
This alleviates the issues of keeping 2 states in 2 different ViewModels and dealing with an additional message flow.
I don’t like Messenger either.
Many people use it because it solves relationing very easy. The usual answer is “it’s good because the systems are not coupled to each other, it’s perfect”.
As bad as it may sound I think coupling is good, when you look at the code you can clearly see and track the depedencies.
In the other hand, someone could wrap a service around the Messenger, and have the service DI injected in view-models 🙂
Completely agree. People think that making code loosely coupled is good even though the logic is tightly coupled.
I like this article, it really made me stop and think, and I think I’ll produce better code as a result.
However, I think you underestimate the benefits of loose coupling, even within a mobile app.
Let me start with a real world example where loose coupling is the ideal solution (hopefully you’re familiar with automotive tech):
All modern cars use a CanBus, it’s a broadcast-only network which almost all electronic components are connected to. A the conceptual level, it is basically identical to the XamarinForms MessagingCenter. Each component on the network sends its messages, and other components are just waiting for messages that they care about.
Example: a sensor in the transmission is reading the current speed of the car, and constantly broadcasting that speed on the bus. Other components like the speedo/odo in the dash will be constantly receiving that speed and displaying it accordingly. But other systems like the braking system will be reading the speed and adjusting how the ABS works. Safety system like the airbags will be watching the speed, they are usually disabled until the car is travelling faster than a certain threshold.
Where this gets really interesting, is when you consider that there are different models of the same car, with different features installed. Some models will have ABS, some will not, some will have airbags, some will not. There’s probably many more features that all use the vehicle speed somehow (speed sensitive wipers… radio increases volume as speed goes up).
Using the CanBus allows the manufacturer to add/remove all those components really easily. Just install it, and plug it into the bus, and they’re done.
If the bus didn’t exist, then they would have to run a new set of wires from each sensor to all components that need it, and it gets really messy really quickly. This would be analogous to parameterizing all pages and viewmodels.
Moving back to a mobile app. Imagine an app that is highly modular, there may be different versions of different components. There may be a free version and a paid version of the app. Or there may be paid or free add-on modules for the app which may or may not be present at any given time.
Using the MessageCenter to decouple all those components allows the developer to make it work 100% with a single easy to manage codebase. To make that scenario work _without_ messaging center would actually be a code maintenance nightmare. You would end up with so many different constructors for a single page, each only getting used once. You’d have to have different versions of code depending on the deployment. You would literally have wiring all over the place, and tracking dependencies would be much more difficult overall.
MessagingCenter, and the concept of loose-coupling allows you to very very easily modularize an app. Sure it comes with it’s problems, dependencies can be unclear at times. But there are very simple ways to deal with that. For example I keep a static class with a list of all the messages that exist. And checking dependencies is as simple as checking for all references of a string.
MessagingCenter does have it’s place. And it’s a great disservice to an amazing tool to say that there are zero situations where it is suitable to use.
Hi Matt
I have just updated this post, as I did find one use for it, background processes. However I still stand by my original opinion, that there would be little to no other uses for it.
I understand the concern about coupling, but we aren’t developing micro services, for a large scale web application here, this is a single mobile application.
Personally I wouldn’t give MessagingCenter the responsibility for determining licensing. Broadcasting out, we are on the free version, and expecting each to pickup a message and deal with it, would likely lead to many issues.
I would recommend creating a LicenseService, and inject that into each place as required. The ViewModel’s or Services can then call this service to determine it’s status and provide the appropriate response, if you are leaving it up to the ViewModel’s to determine their own status based on this information.
If it’s a game, then there are likely background processes running, pushing out updates, and hence messaging center might have some use here.
Thanks
Adam
In my case I am using the messagingCenter to send messages from the platfrom project .
I am working with TV apps , which is not natively supported in XF. So I basically in the android project listen to keystrokes , and when a user press something on the remote controls it triggers “OnKeyDown” and “OnKeyUp” events. So when that happens I send a message to XF components using MessagingCenter.
Do you have an alternative way to do so ?
I have a question for you , What do you think of a page listening to an event from its ViewModel? So the page can DisplayAlert() ? do you have another way to do so ?
While I don’t have the specifics of your project, the keypress is either part of a visual element or a service in Android. If its a visual element I would create a custom renderer and pass the information back through the control. If its a service, you can simply dependency injection your service to be called or listened from in your portable library.
A quick way is DisplayAlert can be called by Application.Current.MainPage.DisplayAlert from the ViewModel, however I would recommend you look at your MVVM Helper Library that would most likely have implemented that better for you.
Well it is a method that can be overrriden from MainActivity , just like onCreate and OnStart. Don’t know where do you put that as a category .
You would create a class, that implements an interface and create a new instance of it in MainActivity. This class will have properties that are Action’s.
You can pass this class down via the new App() or put in in your DI framework.
Then assign those Actions in your portable library.
In MainActivity you can then call the Actions with OnKeyPressed?.Invoke(); This will call straight into your Portable without any need for MessagingCenter and gives you a direct, straight forward debugging path and code execution.
Nice thanks a lot 🙂
I’ve used it in following instance.
Toolbar item on a content page inside a navigation page.
Tollbar item needs to hide/show based on a property inside a ViewModel bound to the page
Is there any workaround to that?
Since the property isn’t just available to the ViewModel, it could be extracted to its own class. This class can then be injected into the service that handles the NavigationPage and the ViewModel.
This allows you to see how they reference each other and not have a global event flying around your app. Basically its having a shared class/entity between them, and its similar to the MessagingCenter approach but more tightly controlled.
Hi, first of all my congratulations for the post, it’s good your analysis.
My case is this:
1) I have ViewModel call intranetViewModel where are the binding of the page intranet.xaml
2) I have a class called service, which connects to webservice (asmx) and brings the data to display in view
public class Service{
public void GetPost(){
intranetServoce.PostAsync();
intranetServoce.PostAsyncCompleted += (object sender, PostAsyncCompletedEventArgs e) =>
{
data= e.Result;
};
}
}
3) From the viewmodel called the method to bring the data
Service = services= new Service();
services.GetPost();
4) When the service responds, I have to use that data and load a viewmodel list so that it is shown in lisview
The only mechanism I found to do this was the MessagingCenter. Do you think it can be done differently?
To trigger the download, I imagine your ViewModel, would call your Model, that would then call your Service?
In that case your ViewModel has a direct line of reference to the service, and should just use the returned result.
Hi, thank you for you answer.
That is the problem, as you should know the service call is asynchronous and in asmx does not implement async and await. So I can not implement a return.
The viewmodel calls the method in the service class, and continues its execution, does not wait for response.
Then the way I found for the service to notify and send the response data to viewmodel, was using MessagingCenter
I would then wrap around the function and make it manually wait for the response, using something like a ManualResetEvent.
e.g.
var reset = new ManualResetEvent(false);
// Make call to asmx
await Task.Run(() => reset.WaitOne() );
// Return the result
The result will come from another variable, where ever the return result comes back from the webservice, do reset.Set(); and store the value.
Otherwise, it would be just using a event chain back, in which case its almost no different than the MessagingCenter.
But again, this might be overkill if its just a simple application.
In the end I prefer to make an asynchronous call encapsulation as I show in this link.
http://stackoverflow.com/questions/37122222/async-await-call-to-asmx-service
I think it’s the same as you said, but I’m not sure.
The important thing is that if you can delete the MessagingCenter that you are using.
Is this a good practice?
Yes that is what I was referring to, however they explain it better than me 🙂
Then you don’t need MessagingCenter at all.
You know, I found another problem, and I sent a variable by reference to handle the issue of errors, but in this process of encapsulating with async and await you can not use variable for that type then choose to create a standard object that goes To return all services
Public class AnswerService
{
Public bool EsCorrecto {get; set; }
Public string Error {get; set; }
Public int Code {get; set; }
Public string Exception {get; set; }
Public Object Result {get; set; }
}
It is assumed that the result should be the data that before I returned the function (List, string, bool, Object etc)
When I call the service and the result variable is a List for example gives this error
Error generating XML document. —> The System.Collections.Generic.List` type can not be used in this context.
Try with an array and neither, I do not know if you can do this in this asmx schema because I know that internally there is a mapping of the service q does .net when generating the proxy in the client and object is generic.
How could I solve this or what alternative could I use to return both the data and the object of error?
Hi Adam,
I am implementing Master Detail Page. I have three different classes i.e. One Master Page, One Detail Page & One MasterDetail Page. My Master contains few items. Once i select item from master page, i need to inform MasterDetail Page that which item is being selected so that it can assign Detail Page. In order to inform MasterDetail page from Master Page, i have used MessagingCenter.
Is there any other alternative that you can suggest ? One way is that i can use one class for Master & MasterDetail Page.
I created a public method is MasterDetail Page which i am calling from Master Page after selecting item. I hope this is better than using MessagingCenter.
This depends if you are using an MVVM library. Most allow you to pass a parameter through in a navigation request.
Hence the best way is to actually pass a parameter through on the Push. If you are doing it directly, e.g. .PushAsync(new Page1());, then I would pass the parameter through here, such as .PushAsync(new Page1(myObject));
Moral of the story, use parameters 🙂 Its better to directly pass through rather than through a MessagingCenter.
I’m currently planning to use MessagingCenter for Push Notifications. I’m using the PushNotification Xamarin Forms Plugin and in the OnMessage I want to notify all pages that care about new push notifications that a new notification has been received. This includes a top level page and sub-level pages that show a “badge” of the new message by Id. What are your thoughts in this scenario?
This may be a case for using MessagingCenter, depending upon what you are exactly trying to do. Normally with Push Notifications, they will show a message and the user will click on them or ignore them. Either way in that scenario, no need for MessagingCenter because you would just pass the information along with the user click.
However, if you need to notify the current page, a message has been received, since PushNotifications are technically almost a different process or background task, using MessagingCenter to notify any pages that need to know when a message is received to update a badge count, seems like a valid use.
Do you have any example code regarding this Messaging Center?
I’ve created a “NotificationService” that holds a list of notifications like “Offline”, “Success” etc, that get rendered at the top of every page that borrows from the “BasePage” in my Xamarin Forms app…
I use the MessagingCenter to send messages that the NotificationsList has changed to all the baseviewmodels linked to a basepages which i then trigger an OnPropertyChanged(“Notifications”) within the baseviewmodel. I did this because when I change the NotificationsList in the Service, the viewmodels that I’ve tried to point or equal that list do not react when the list has changed it seems. So using the MessagingCenter ensured viability.
Thoughts?