Misuses Of MessagingCenter

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.

vmtopage

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.

pagetopage

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);

 

vmtovm

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.

modeltomodel

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.

splitmodel

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.

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

28 Comments

  1. Seth

    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?

    1. Adam Pedley

      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.

  2. erwin lee

    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?

    1. Adam Pedley

      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.

  3. Rob

    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 🙂

      1. Matt B

        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.

        1. Adam Pedley

          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

  4. Ahmad Elmadi

    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 ?

    1. Adam Pedley

      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.

      1. Ahmad Elmadi

        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 .

      2. Adam Pedley

        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.

  5. Hiral

    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?

    1. Adam Pedley

      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.

  6. Antonio

    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?

    1. Adam Pedley

      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.

      1. Antonio

        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

        1. Adam Pedley

          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.

              1. Antonio

                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?

  7. Devesh Mishra

    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.

    1. Devesh Mishra

      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.

    2. Adam Pedley

      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.

  8. John Rennemeyer

    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?

    1. Adam Pedley

      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.

Leave A Comment?