Поделиться через


Xamarin.Forms MessagingCenter

Шаблон "публикация-подписка" — это шаблон обмена сообщениями, в котором издатели отправляют сообщение без знания о получателях, известных как подписчики. Аналогичным образом подписчики прослушивают определенные сообщения, не зная издателей.

События в .NET реализуют шаблон публикации и подписки, который представляет собой наиболее простой подход к обеспечению взаимодействия между компонентами, когда слабая связанность не требуется, как в случае с элементом управления и страницей, на которой он находится. Однако время существования издателя и время существования подписчика связаны посредством ссылок объектов друг на друга, и тип подписчика должен ссылаться на тип издателя. Из-за этого могут возникать проблемы с управлением памятью, особенно если существуют кратковременные объекты, которые подписаны на событие статического или долговременного объекта. Если обработчик событий не удаляется, подписчик продолжает существовать из-за ссылки на него в издателе, вследствие чего сборка мусора для подписчика будет отложена или не произойдет.

Класс Xamarin.FormsMessagingCenter реализует шаблон публикации и подписки, позволяя обмен данными между компонентами, которые неудобны для связи по ссылкам на объекты и типы. Этот механизм позволяет издателям и подписчикам взаимодействовать без ссылки друг на друга, помогая уменьшить зависимости между ними.

Класс MessagingCenter предоставляет функцию многоадресной публикации и подписки. Это означает, что может существовать несколько издателей, которые публикуют одно сообщение, и может быть несколько подписчиков, прослушивающих одно и то же сообщение:

Функция многоадресной публикации и подписки

Издатели отправляют сообщения с помощью метода MessagingCenter.Send, а подписчики прослушивают сообщения с помощью метода MessagingCenter.Subscribe. Кроме того, подписчики могут также отменять подписку на сообщения, если это необходимо, с помощью метода MessagingCenter.Unsubscribe.

Внимание

На внутреннем уровне класс MessagingCenter использует слабые ссылки. Это означает, что он не будет поддерживать объекты в активном состоянии и позволит им собирать мусор. Поэтому необходимо отменять подписку на сообщения только в том случае, если классу больше не требуется получать сообщения.

Публикация сообщения

Сообщения MessagingCenter являются строками. Издатели уведомляют подписчиков о сообщении с помощью одной из перегрузок MessagingCenter.Send. Следующий код публикует события Hi.

MessagingCenter.Send<MainPage>(this, "Hi");

В этом примере метод Send задает универсальный аргумент, представляющий отправителя. Чтобы получить сообщение, подписчик также должен указать тот же универсальный аргумент, указывающий, что он прослушивает сообщение от этого отправителя. Кроме того, в этом примере указываются два аргумента метода:

  • Первый аргумент указывает экземпляр отправителя.
  • Второй аргумент указывает само сообщение.

Полезные данные также могут быть отправлены с сообщением:

MessagingCenter.Send<MainPage, string>(this, "Hi", "John");

В этом примере метод Send задает два универсальных аргумента. Первый — это тип, который отправляет сообщение, а второй — тип отправляемых полезных данных. Чтобы получить сообщение, подписчик также должен указать те же универсальные аргументы. Это позволяет разным подписчикам получать несколько сообщений с одним удостоверением сообщения, но различными типами полезных данных. Кроме того, в этом примере задается третий аргумент метода, представляющий полезные данные для отправки подписчику. В этом случае данные — это string.

Метод Send опубликует сообщение и все полезные данные в стиле "отправил и забыл". Поэтому сообщение отправляется, даже если отсутствуют подписчики, зарегистрированные для получения сообщения. В этом случае отправленное сообщение игнорируется.

Оформление подписки на сообщение

Подписчики могут зарегистрироваться для получения сообщения с помощью одной из перегрузок MessagingCenter.Subscribe. В следующем коде показан пример такого действия:

MessagingCenter.Subscribe<MainPage> (this, "Hi", (sender) =>
{
    // Do something whenever the "Hi" message is received
});

В этом примере метод Subscribe подписывает объект this на сообщения Hi, отправляемые типом MainPage, и выполняет делегат обратного вызова в ответ на получение сообщения. Делегат обратного вызова, указанный в качестве лямбда-выражения, может быть кодом, который обновляет пользовательский интерфейс, сохраняет данные или запускает другую операцию.

Примечание.

Подписчику может не потребоваться обрабатывать каждый экземпляр опубликованного сообщения, и это можно контролировать с помощью аргументов универсального типа, указанных в методе Subscribe.

Следующий пример демонстрирует, как подписаться на сообщение, содержащее полезные данные.

MessagingCenter.Subscribe<MainPage, string>(this, "Hi", async (sender, arg) =>
{
    await DisplayAlert("Message received", "arg=" + arg, "OK");
});

В этом примере метод Subscribe подписывается на сообщения Hi, отправляемые типом MainPage, полезные данные которого — string. В ответ на получение такого сообщения выполняется делегат обратного вызова, который отображает полезные данные в оповещении.

Внимание

Делегат, который выполняется методом Subscribe, будет выполняться в том же потоке, который публикует сообщение с помощью метода Send.

Отмена подписки на сообщение

Если подписчики больше не должны получать сообщения, можно отменить подписку на них. Для этого используется одна из перегрузок MessagingCenter.Unsubscribe.

MessagingCenter.Unsubscribe<MainPage>(this, "Hi");

В этом примере метод Unsubscribe отменяет подписывание объекта this на сообщения Hi, отправляемые типом MainPage.

Подписку на сообщения, содержащие полезные данные, необходимо отменять с помощью перегрузки Unsubscribe, указывающей два универсальных аргумента:

MessagingCenter.Unsubscribe<MainPage, string>(this, "Hi");

В этом примере метод Unsubscribe отменяет подписывание объекта this на сообщения Hi, отправляемые типом MainPage, полезные данные которого — string.