Komunikace mezi volně propojenými komponentami
Tip
Tento obsah je výňatek z elektronické knihy, vzory podnikových aplikací pomocí .NET MAUI, dostupné na .NET Docs nebo jako zdarma ke stažení PDF, které lze číst offline.
Model publikování a odběru je model zasílání zpráv, ve kterém vydavatelé odesílají zprávy, aniž by znali příjemce, označované jako odběratelé. Podobně předplatitelé poslouchají konkrétní zprávy, aniž by znali žádné vydavatele.
Události v .NET implementují model publikování a odběru a představují nejjednodušší přístup pro komunikační vrstvu mezi komponentami, pokud není vyžadována volné párování, například ovládací prvek a stránka, která ho obsahuje. Životnost vydavatele a odběratele jsou však vzájemně svázány odkazy na objekty a typ odběratele musí mít odkaz na typ vydavatele. To může způsobit problémy se správou paměti, zejména pokud existují krátkodobé objekty, které se přihlašují k odběru události statického nebo dlouhodobého objektu. Pokud obslužná rutina události není odebrána, odběratel bude udržován naživu odkazem na ni v vydavateli a tím se zabrání nebo zpozdí uvolnění paměti odběratele.
Úvod do MVVM Toolkit Messenger
Rozhraní MVVM Toolkit IMessenger
popisuje model publikování a odběru, který umožňuje komunikaci založenou na zprávách mezi komponentami, které jsou nevhodné pro propojení podle odkazů na objekty a typy. Tento mechanismus umožňuje vydavatelům a odběratelům komunikovat bez přímého odkazu na sebe, což pomáhá snižovat závislosti mezi komponentami a zároveň umožňuje nezávisle vyvíjet a testovat komponenty.
Poznámka:
MVVM Toolkit Messenger je součástí CommunityToolkit.Mvvm
balíčku. Informace o tom, jak přidat balíček do projektu, naleznete v tématu Úvod do MVVM Toolkit na webu Microsoft Developer Center.
Upozorňující
.NET MAUI obsahuje integrovanou MessagingCenter
třídu, která se už nedoporučuje používat. Místo toho použijte MVVM Toolkit Messenger.
Rozhraní IMessenger
umožňuje funkci publikování a odběru vícesměrového vysílání. To znamená, že může existovat více vydavatelů, kteří publikují jednu zprávu, a můžou mít více odběratelů, kteří naslouchají stejné zprávě. Následující obrázek znázorňuje tento vztah:
Existují dvě implementace IMessenger
rozhraní, které jsou součástí CommunityToolkit.Mvvm
balíčku. Používá WeakReferenceMessenger
slabé odkazy, které můžou vést k jednoduššímu vyčištění pro předplatitele zpráv. To je dobrá volba, pokud předplatitelé nemají jasně definovaný životní cyklus. Používá StrongReferenceMessenger
silné odkazy, které můžou vést k lepšímu výkonu a jasně řízené životnosti předplatného. Pokud máte pracovní postup s velmi řízenou životností (například předplatné, které je vázané na stránku OnAppearing
a OnDisappearing
metody), StrongReferenceManager
může být lepší volbou, pokud se jedná o problém. Obě tyto implementace jsou k dispozici s výchozími implementacemi připravenými k použití odkazem na buď WeakReferenceMessenger.Default
nebo StrongReferenceMessenger.Default
.
Poznámka:
IMessenger
I když rozhraní umožňuje komunikaci mezi volně propojenými třídami, nenabízí jediné architektonické řešení tohoto problému. Například komunikaci mezi modelem zobrazení a zobrazením lze dosáhnout také vazbovým modulem a oznámeními o změnách vlastností. Kromě toho lze komunikaci mezi dvěma modely zobrazení dosáhnout také předáváním dat během navigace.
Multiformní aplikace eShop používá WeakReferenceMessenger
třídu ke komunikaci mezi volně propojenými komponentami. Aplikace definuje jednu zprávu s názvem AddProductMessage
. Třída AddProductMessage
publikuje CatalogViewModel
při přidání položky do nákupního košíku. Třída se pak CatalogView
přihlásí k odběru zprávy a použije ji ke zvýraznění produktu, který přidá pomocí animace v odpovědi.
V aplikaci WeakReferenceMessenger
eShop pro více platforem se používá k aktualizaci uživatelského rozhraní v reakci na akci, ke které dochází v jiné třídě. Zprávy jsou proto publikovány z vlákna, na které třída provádí, s odběrateli, kteří obdrží zprávu ve stejném vlákně.
Tip
Při provádění aktualizací uživatelského rozhraní zařazujte do uživatelského rozhraní nebo hlavního vlákna. Pokud nejsou v tomto vlákně provedeny aktualizace uživatelských rozhraní, může dojít k chybovému ukončení nebo nestabilitě aplikace.
Pokud je k aktualizaci uživatelského rozhraní vyžadována zpráva odeslaná z vlákna na pozadí, zpracujte zprávu ve vlákně uživatelského rozhraní odběratele vyvoláním MainThread.BeginInvokeOnMainThread
metody.
Další informace o Messenger
aplikaci Messenger naleznete v centru Microsoft Developer Center.
Definování zprávy
IMessenger
zprávy jsou vlastní objekty, které poskytují vlastní datové části. Následující příklad kódu ukazuje AddProductMessage
zprávu definovanou v aplikaci eShop pro více platforem:
public class AddProductMessage : ValueChangedMessage<int>
{
public AddProductMessage(int count) : base(count)
{
}
}
Základní třída je definována pomocí, ValueChangedMessage<T>
kde T
může být libovolný typ potřebný k předávání dat. Vydavatelé i odběratelé zpráv mohou očekávat zprávy určitého typu (například AddProductMessage
). To může pomoci zajistit, aby obě strany souhlasily se smlouvou o zasílání zpráv a že data poskytnutá s touto smlouvou budou konzistentní. Kromě toho tento přístup poskytuje podporu bezpečnosti typů kompilace a refaktoringu.
Publikování zprávy
K publikování zprávy budeme muset použít metodu IMessenger.Send
. K tomuto přístupu lze přistupovat nejčastěji prostřednictvím WeakReferenceMessenger.Default.Send
nebo StrongReferenceMessenger.Default.Send
. Odeslaná zpráva může být libovolného typu objektu. Následující příklad kódu ukazuje publikování AddProduct
zprávy:
WeakReferenceMessenger.Default.Send(new Messages.AddProductMessage(BadgeCount));
V tomto příkladu Send
metoda určuje novou instanci objektu AddProductMessage
pro příjem podřízených odběratelů. Další druhý parametr tokenu lze přidat, aby bylo možné použít, když více odběratelů potřebuje přijímat zprávy stejného typu bez přijetí nesprávné zprávy.
Metoda Send
publikuje zprávu a její data datové části pomocí přístupu typu fire-and-forget. Zpráva je proto odeslána i v případě, že nejsou zaregistrovaní žádní odběratelé, kteří zprávu obdrží. V takové situaci se odeslaná zpráva ignoruje.
Přihlášení k odběru zprávy
Odběratelé se mohou zaregistrovat k přijetí zprávy pomocí jednoho z IMessenger.Register<T>
přetížení. Následující příklad kódu ukazuje, jak se eShop multiplatformní aplikace přihlásí k odběru a zpracovává AddProductMessage
zprávu:
WeakReferenceMessenger.Default
.Register<CatalogView, Messages.AddProductMessage>(
this,
async (recipient, message) =>
{
await recipient.Dispatcher.DispatchAsync(
async () =>
{
await recipient.badge.ScaleTo(1.2);
await recipient.badge.ScaleTo(1.0);
});
});
V předchozím příkladu Register
se metoda přihlásí k odběru AddProductMessage
zprávy a spustí delegát zpětného volání v reakci na přijetí zprávy. Tento delegát zpětného volání zadaný jako výraz lambda spustí kód, který aktualizuje uživatelské rozhraní.
Poznámka:
Vyhněte se použití delegáta zpětného this
volání, abyste se vyhnuli zachycení tohoto objektu v rámci delegáta. To může pomoct zvýšit výkon. Místo nich zadejte parametr recipient
.
Pokud jsou data datové části zadaná, nepokoušejte se upravovat data datové části z delegáta zpětného volání, protože k přijatým datům může současně přistupovat několik vláken. V tomto scénáři by data datové části měla být neměnná, aby nedocházelo k chybám souběžnosti.
Zrušení odběru ze zprávy
Odběratelé si můžou odhlásit odběr zpráv, které už nechtějí dostávat. Toho dosáhnete pomocí jednoho z IMessenger.Unregister
přetížení, jak je znázorněno v následujícím příkladu kódu:
WeakReferenceMessenger.Default.Unregister<Messages.AddProductMessage>(this);
Poznámka:
V tomto příkladu není zcela nutné volat Unregister
, protože WeakReferenceMessenger
umožní, aby nepoužívané objekty byly uvolněny z paměti. Pokud by se StrongReferenceMessenger
použilo, doporučujeme volat Unregister
pro všechna předplatná, která se už nepoužívají.
V tomto příkladu Unsubscribe
syntaxe metody určuje argument typu zprávy a objekt příjemce, který naslouchá zpráv.
Shrnutí
Rozhraní MVVM Toolkit IMessenger
popisuje model publikování a odběru, který umožňuje komunikaci založenou na zprávách mezi komponentami, které jsou nevhodné pro propojení podle odkazů na objekty a typy. Tento mechanismus umožňuje vydavatelům a odběratelům komunikovat bez vzájemné vazby, což pomáhá snižovat závislosti mezi komponentami a zároveň umožňuje nezávisle vyvíjet a testovat komponenty.