Форма Xamarin Отмена подписки MessagingCenter не работает должным образом

Функциональность, написанная внутри MessagingCenter.Subscribe(), вызывается несколько раз, когда я перемещаюсь туда и обратно несколько раз в приложении. Но каждый раз перед подпиской я отменяю подписку на то же самое в конструкторе, как показано ниже, но это не сработало.

MessagingCenter.Unsubscribe<SubmitPage>(this,"Save");
MessagingCenter.Subscribe<SubmitPage>(this, "Save", (sender) =>
{
   DisplayToastOnSuccessfulSubmission();
});

В моем приложении у меня есть 6 страниц ( git), и я сохраняю данные на 6-й странице с помощью MessagingCenter.Send, и то же самое будет подписано на 2-й странице, а сохраненное сообщение будет отображаться на 2-й странице (после перехода на эту страницу).

Теперь я перемещаюсь как 2->1->2->3->4->5->6 в этом конкретном случае DisplayToastOnSuccessfulSubmission() будет вызван два раза (потому что конструктор Page2 вызывается дважды).

Я даже пытался поместить тот же код в OnAppearing. Я не могу отменить подписку в OnDisappear, так как мне нужно, чтобы проводка события была до того момента, когда я достигну Page6 для сохранения.

Воспроизведено то же поведение в примере проекта и добавлено здесь https://github.com/suchithm/MessageCenterSampleApp
Drop box link

Как правильно это сделать?

4 ответа

Решение

Но каждый раз перед подпиской я отменяю подписку на то же самое в конструкторе, как показано ниже, но это не сработало.

MessagingCenter.Subscribe() вызывается несколько раз, потому что в вашем коде есть два экземпляра Page2, оба они используют MessagingCenter.Subscribe() метод, поэтому Unsubscribe не работал

Вы можете изменить page2() в одиночку, чтобы убедиться, что есть только один экземпляр Page2 в вашем проекте, после этого, когда вы отправляете сообщение, MessagingCenter.Subscribe() вызывается только один раз.

Page2.cs:

public static Page2 instance = new Page2();

public static Page2 GetPage2Instance()
{
    if(instance == null)
    {
        return new Page2();
    }
    return instance;
}

private Page2()
{
    InitializeComponent();
    MessagingCenter.Unsubscribe<Page2>(this, "SaveToastPage2");
    MessagingCenter.Subscribe<Page2>(this, "SaveToastPage2", (sender) =>
    {
       DisplayToastOnSuccessfulSubmission();
    }
 }

Когда вы отправляете сообщение:

MessagingCenter.Send(Page2.GetPage2Instance(), "SaveToastPage2");

РЕДАКТИРОВАТЬ:

Помните, что объявление конструкторов Page2 класс, чтобы быть частным, чтобы убедиться, что есть только один экземпляр Page2 в вашем проекте уверен.

private Page2()
{
   ...
}

Изменить ваш Page1.cs код:

async void Handle_Next(object sender, System.EventArgs e)
{
    await App.NavigationRef.PushAsync(Page2.GetPage2Instance(), true);
}

Я столкнулся с той же проблемой. Я решил проблему, передав те же параметры inn subscribe и unsubscribe.

MessagingCenter.Subscribe<Page1, T>(this, "Listen", async (Page1 arg1, T 
listenedString) =>
{

});

Отпишитесь, как показано ниже

 MessagingCenter.Unsubscribe<Page1, T>(this, "Listen");

I'm using this temporary solution.I declared a static dictionary to storage my object (to this example I used an object type).

      private static Dictionary<string, object> subscribedReferencePages = new Dictionary<string, object>();

And I always storage the last subscribed page reference. Then I compare the page reference before triggering the message method to fire only the last one.

          subscribedReferencePages[pageName] = this;
    MessagingCenter.Subscribe<ViewModelBase>(this, pageName, async (sender) =>
    {
        if (!ReferenceEquals(sender, this))
        {
            return;
        }

        this.OnInitialized();
    });

To call the message method I need to pass the dictionary as parameter (instead of the "this" reference).

       MessagingCenter.Send(subscribedPages[pageName], keyPageName);

Вместо того, чтобы отписаться при переходе на страницу, отмените подписку при переходе в сторону ОТ страницы. В этот момент ваш экземпляр "этого" остается тем же "этим", как вы думаете.

Другие вопросы по тегам