Sdílet prostřednictvím


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.

Vzory podnikových aplikací pomocí úvodní miniatury eBooku .NET MAUI

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:

Funkce publikování a odběru vícesměrového vysílání

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 Messengeraplikaci 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.