Sdílet prostřednictvím


Komunikace mezi volně vázanými komponentami

Poznámka:

Tato elektronická kniha byla publikována na jaře roku 2017 a od té doby nebyla aktualizována. Existuje mnoho v knize, která zůstává cenná, ale některé materiály jsou zastaralé.

Model publikování a odběru je vzor zasílání zpráv, ve kterém vydavatelé odesílají zprávy bez znalosti příjemců, označovaných jako odběratelé. Podobně předplatitelé poslouchají konkrétní zprávy bez znalosti vydavatelů.

Události v .NET implementují model publikování a odběru a představují nejjednodušší a 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 MessagingCenter

Třída Xamarin.FormsMessagingCenter implementuje model publikování a odběru, což umožňuje komunikaci založenou na zprávách mezi komponentami, které jsou nevhodné pro propojení podle objektů a odkazů na 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.

Třída MessagingCenter poskytuje 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 pro stejnou zprávu může naslouchat více odběratelům. Obrázek 4-1 znázorňuje tuto relaci:

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

Obrázek 4-1: Funkce publikování a odběr vícesměrového vysílání

Vydavatelé odesílají zprávy pomocí MessagingCenter.Send metody, zatímco předplatitelé naslouchají MessagingCenter.Subscribe zprávám pomocí metody. Předplatitelé také můžou odběry zpráv odhlásit, pokud je to potřeba, pomocí MessagingCenter.Unsubscribe této metody.

Interně třída MessagingCenter používá slabé odkazy. To znamená, že neudrží objekty naživu a umožní jim uvolňování paměti. Proto by mělo být nutné odhlásit odběr zprávy pouze v případě, že třída již nechce zprávu přijmout.

Mobilní aplikace eShopOnContainers používá MessagingCenter třídu ke komunikaci mezi volně propojenými komponentami. Aplikace definuje tři zprávy:

  • Zpráva AddProduct je publikována CatalogViewModel třídou při přidání položky do nákupního košíku. Třída se zase BasketViewModel přihlásí k odběru zprávy a v odpovědi zvýší počet položek v nákupním košíku. Kromě toho se BasketViewModel třída také odhlásí z této zprávy.
  • Zpráva Filter je publikována CatalogViewModel třídou, když uživatel použije filtr značky nebo typu na položky zobrazené z katalogu. Třída se zase CatalogView přihlásí k odběru zprávy a aktualizuje uživatelské rozhraní tak, aby se zobrazily jenom položky, které odpovídají kritériím filtru.
  • Zpráva ChangeTab je publikována MainViewModel třídou, když CheckoutViewModel přejde na MainViewModel následující úspěšné vytvoření a odeslání nové objednávky. Třída se zase MainView přihlásí k odběru zprávy a aktualizuje uživatelské rozhraní tak, aby byla aktivní karta Můj profil , aby se zobrazily objednávky uživatele.

Poznámka:

MessagingCenter I když třída 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.

V mobilní aplikaci MessagingCenter eShopOnContainers se používá k aktualizaci v uživatelském rozhraní v reakci na akci, která se vyskytuje v jiné třídě. Zprávy se proto publikují ve vlákně uživatelského rozhraní 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 vlákna uživatelského rozhraní. 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 Device.BeginInvokeOnMainThread metody.

Další informace naleznete v MessagingCentertématu MessagingCenter.

Definování zprávy

MessagingCenter zprávy jsou řetězce, které slouží k identifikaci zpráv. Následující příklad kódu ukazuje zprávy definované v mobilní aplikaci eShopOnContainers:

public class MessageKeys  
{  
    // Add product to basket  
    public const string AddProduct = "AddProduct";  

    // Filter  
    public const string Filter = "Filter";  

    // Change selected Tab programmatically  
    public const string ChangeTab = "ChangeTab";  
}

V tomto příkladu se zprávy definují pomocí konstant. Výhodou tohoto přístupu je, že zajišťuje bezpečnost typů kompilace a podporu refaktoringu.

Publikování zprávy

Vydavatelé upozorňují odběratele na zprávu s jedním z MessagingCenter.Send přetížení. Následující příklad kódu ukazuje publikování AddProduct zprávy:

MessagingCenter.Send(this, MessageKeys.AddProduct, catalogItem);

V tomto příkladu Send metoda určuje tři argumenty:

  • První argument určuje třídu odesílatele. Třída odesílatele musí být určena všemi odběrateli, kteří chtějí zprávu obdržet.
  • Druhý argument určuje zprávu.
  • Třetí argument určuje data datové části, která se mají odeslat odběrateli. V tomto případě jsou CatalogItem data datové části instancí.

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.

Poznámka:

Metoda MessagingCenter.Send může použít obecné parametry k řízení způsobu doručení zpráv. Více zpráv, které sdílejí identitu zprávy, ale odesílají různé datové typy datové části, můžou přijímat různí odběratelé.

Přihlášení k odběru zprávy

Odběratelé se mohou zaregistrovat k přijetí zprávy pomocí jednoho z MessagingCenter.Subscribe přetížení. Následující příklad kódu ukazuje, jak se mobilní aplikace eShopOnContainers přihlásí k odběru a zpracuje AddProduct zprávu:

MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(  
    this, MessageKeys.AddProduct, async (sender, arg) =>  
{  
    BadgeCount++;  

    await AddCatalogItemAsync(arg);  
});

V tomto příkladu Subscribe se metoda přihlásí k odběru AddProduct 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í.

Tip

Zvažte použití neměnných dat datové části. 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.

Odběratel nemusí zpracovávat všechny instance publikované zprávy a to může být řízeno argumenty obecného typu, které jsou zadány v Subscribe metodě. V tomto příkladu odběratel obdrží AddProduct pouze zprávy odeslané z CatalogViewModel třídy, jejichž datová část je CatalogItem instance.

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 MessagingCenter.Unsubscribe přetížení, jak je znázorněno v následujícím příkladu kódu:

MessagingCenter.Unsubscribe<CatalogViewModel, CatalogItem>(this, MessageKeys.AddProduct);

V tomto příkladu Unsubscribe syntaxe metody odráží argumenty typu zadané při přihlášení k odběru AddProduct zprávy.

Shrnutí

Třída Xamarin.FormsMessagingCenter implementuje model publikování a odběru, což umožňuje komunikaci založenou na zprávách mezi komponentami, které jsou nevhodné pro propojení podle objektů a odkazů na 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.