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:
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ánaCatalogViewModel
třídou při přidání položky do nákupního košíku. Třída se zaseBasketViewModel
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 seBasketViewModel
třída také odhlásí z této zprávy. - Zpráva
Filter
je publikovánaCatalogViewModel
třídou, když uživatel použije filtr značky nebo typu na položky zobrazené z katalogu. Třída se zaseCatalogView
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ánaMainViewModel
třídou, kdyžCheckoutViewModel
přejde naMainViewModel
následující úspěšné vytvoření a odeslání nové objednávky. Třída se zaseMainView
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 MessagingCenter
té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.