MessaggingCenter - Anyone seeing issues with anonymous messages not being heard by subscriber?

ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

I just lodged this as a bug:
https://github.com/xamarin/Xamarin.Forms/issues/5809

But was wondering if anyone else is seeing this.

Description

Generally a MessageCenter message subscription it for a message sent from a specific class.
But it can also be anonymous in the sense that any class can .Send a message and any class will hear it.

For example:
Subscribe:
MessagingCenter.Subscribe<string>(this,"ISENGINEON",OnEngineOnChanged);//Subscribe without caring who is sending the message.

Send:
MessagingCenter.Send("ISENGINEON", true.ToString());//Shared layer view models subscribe and react

You see it discussed with successful results back in Jan of 2018
https://stackoverflow.com/questions/48047444/xamarin-android-how-do-i-pass-an-event-from-mainactivity-to-viewmodel-on-forms

Yet... Now, it seem to no longer work. I'm testing in VS2019 with both 3.6.x stable and 4.0-pre

The subscribe takes place... the send takes place... The subscriber however never hears the message and thus never executes the handler method.

Steps to Reproduce

  1. Any simple Xamarin app. "Welcome to Xamarin Forms" is fine. Add a button on the page
                    <Button
                        x:Name="Test"
                        Clicked="Test_OnClicked"
                        Text="Test" />
  1. Add a handler for the button in the code behind
        private void Test_OnClicked(object sender, EventArgs e)
        {
            Console.WriteLine("INFORMATION: Test Button Clicked.");
             MessagingCenter.Send("ISENGINEON", true.ToString());//Shared layer view models subscribe and react
       }
  1. Add a subscriber anywhere you like. I use the constructor of a view model
            MessagingCenter.Subscribe<string>(this,"ISENGINEON",OnEngineOnChanged);//Subscribe without caring who is sending the message. This is how we can hear from Android project without being able to reference MainActivity or a Broadcast receiver.
  1. Add the handler from the subscription
        private void OnEngineOnChanged(string obj)
        {
            Console.WriteLine("INFORMATION> Well heck, it worked");
        }
  1. Run the app
  2. Add breakpoints as desired for confirmation

Expected Behavior

When you click the button the message is sent - That is confirmed with breakpoints.
The subscriber should then run the assigned handler.

Actual Behavior

The handler is never executed. Indicating the subscriber never hears the message.

Best Answers

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    I always use with a "class". I have never been able to use without it. If I don't have a "class", I use "App"

  • JohnHardmanJohnHardman GBUniversity mod
    edited April 4

    Like @AlessandroCaliaro , I always use a class, sometimes using Application as the class and Application.Current as the instance.

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Ditto I have always used it with as a class as well.
    Until now. I have a desire to send a message up from the Android layer to the agnostic layer.
    Well... You can't directly reference the OS specific classes from the agnostic layer.

    The idea here is that the Android MainActivity or an Android BroadcastListener should be able to yell out a message and the agnostic layer can hear it. The same could be true for the iOS equivalent. And the agnostic layer would hear it regardless of platform its running on.

    Same use-case as this StackOverflow discussion from Jan2018 - where everyone says they had success.
    https://stackoverflow.com/questions/48047444/xamarin-android-how-do-i-pass-an-event-from-mainactivity-to-viewmodel-on-forms

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    You're a lifesaver @JohnHardman

    A couple interesting things about that once it worked.
    Even one side of Visual Studio realized that you don't have to specify the type in the sending <> so long as you have it in the call.

    This still works

    MessagingCenter.Subscribe<Application,string>(this,"ISENGINEON",OnEngineOnChanged);
    // along with
    MessagingCenter.Send(Application.Current,"ISENGINEON", true.ToString());
    // Notice there are no types specified in < , >
    

    That was with both the sender and subscriber within the shared/agnostic layer. Test small in baby steps, right?

    So... Next step: Does it work from the Android layer sending and the shared layer subscribing?

    Android Broadcast listener:
    MessagingCenter.Send(Xamarin.Forms.Application.Current,"ISENGINEON", result.ToString());
    Shared layer view model
    MessagingCenter.Subscribe<Application,string>(this,"ISENGINEON",OnEngineOnChanged);

    Success

    You're a prince among men, John!

  • gonzz0gonzz0 Member
    edited July 26

    Hi, don't know if this is relevant, but I tried above to send a message with an arg uri that I receive from a Deeplink to launch my App in the MainActivity OnCreate. The subscriber is on a viewmodel that gets started a few lines earlier when te new App(_platform) runs, at which stage the Ioc layers and the viewmodels are instantiated)
    This however doesn't seem to work; is there a workaround? Or should I abandon the idea of using a message in this case?

Sign In or Register to comment.