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
.