Kommunikation zwischen lose gekoppelten Komponenten
Hinweis
Dieses eBook wurde im Frühjahr 2017 veröffentlicht und wurde seitdem nicht aktualisiert. Es gibt viel in dem Buch, das wertvoll bleibt, aber einige der Materialien sind veraltet.
Das Veröffentlichen-Abonnieren-Muster ist ein Messagingmuster, bei dem Herausgeber Nachrichten senden, ohne über Kenntnisse zu Empfängern zu verfügen, die als Abonnenten bezeichnet werden. Auf ähnliche Weise lauschen Abonnenten auf bestimmte Nachrichten, ohne dass sie über Kenntnisse zu Herausgebern verfügen.
Ereignisse in .NET implementieren das Veröffentlichen-Abonnieren-Muster und sind der einfachste und unkomplizierteste Ansatz für eine Kommunikationsschicht zwischen Komponenten, wenn keine lose Kopplung erforderlich ist, wie beispielsweise ein Steuerelement und die Seite, die es enthält. Die Lebensdauer von Herausgeber und Abonnent sind jedoch durch Objektverweise miteinander gekoppelt, und der Abonnententyp muss einen Verweis auf den Herausgebertypen haben. Dies kann zu Problemen bei der Speicherverwaltung führen, insbesondere wenn es kurzlebige Objekte gibt, die ein Ereignis eines statischen oder langlebigen Objekts abonnieren. Wenn der Ereignishandler nicht entfernt wird, bleibt der Abonnent durch den Verweis darauf im Herausgeber erhalten, was die Garbage Collection des Abonnenten verhindert oder verzögert.
Einführung in MessagingCenter
Die Xamarin.FormsMessagingCenter
Klasse implementiert das Veröffentlichungsabonnent-Muster, sodass nachrichtenbasierte Kommunikation zwischen Komponenten, die unannehlich sind, um eine Verknüpfung nach Objekt- und Typverweise zu ermöglichen. Dieser Mechanismus ermöglicht die Kommunikation zwischen Herausgebern und Abonnenten, ohne dass ein Verweis aufeinander besteht, und trägt dazu bei, die Abhängigkeiten zwischen Komponenten zu verringern. Zudem können Komponenten unabhängig voneinander entwickelt und getestet werden.
Die MessagingCenter
-Klasse bietet Multicast-Funktionen zum Veröffentlichen und Abonnieren. Dies bedeutet, dass mehrere Herausgeber vorhanden sein können, die eine einzelne Nachricht veröffentlichen, und mehrere Abonnenten, die auf dieselbe Nachricht lauschen. Abbildung 4-1 veranschaulicht diese Beziehung:
Abbildung 4-1: Multicast-Funktionalität für Veröffentlichungsabonnent
Herausgeber senden Nachrichten mithilfe der MessagingCenter.Send
-Methode, während Abonnenten mithilfe der MessagingCenter.Subscribe
-Methode auf Nachrichten lauschen. Darüber hinaus können Abonnenten bei Bedarf mit der MessagingCenter.Unsubscribe
-Methode auch Nachrichtenabonnements kündigen.
Intern verwendet die MessagingCenter
-Klasse schwache Verweise. Dies bedeutet, dass Objekte nicht aktiv bleiben und Garbage Collection ermöglicht wird. Daher sollte es nur erforderlich sein, eine Nachricht zu kündigen, wenn eine Klasse die Nachricht nicht mehr empfangen möchte.
Die mobile eShopOnContainers-App verwendet die MessagingCenter
Klasse, um zwischen lose gekoppelten Komponenten zu kommunizieren. Die App definiert drei Nachrichten:
- Die
AddProduct
-Nachricht wird von derCatalogViewModel
-Klasse veröffentlicht, wenn ein Element dem Warenkorb hinzugefügt wird. Im Gegenzug abonniert dieBasketViewModel
Klasse die Nachricht und erhöht die Anzahl der Elemente im Warenkorb als Antwort. Darüber hinaus gekündigt derBasketViewModel
Kurs auch diese Nachricht. - Die
Filter
Nachricht wird von derCatalogViewModel
Klasse veröffentlicht, wenn der Benutzer einen Marken- oder Typfilter auf die im Katalog angezeigten Elemente anwendet. Im Gegenzug abonniert dieCatalogView
Klasse die Nachricht und aktualisiert die Benutzeroberfläche, sodass nur Elemente angezeigt werden, die den Filterkriterien entsprechen. - Die
ChangeTab
Nachricht wird von derMainViewModel
Klasse veröffentlicht, wenn dieCheckoutViewModel
Navigation zurMainViewModel
folgenden erfolgreichen Erstellung und Übermittlung einer neuen Bestellung erfolgt. Im Gegenzug abonniert dieMainView
Klasse die Nachricht und aktualisiert die Benutzeroberfläche so, dass die Registerkarte "Mein Profil " aktiv ist, um die Bestellungen des Benutzers anzuzeigen.
Hinweis
Die MessagingCenter
-Klasse ermöglicht zwar die Kommunikation zwischen lose gekoppelten Klassen, bietet aber nicht die einzige Architekturlösung für dieses Problem. Beispielsweise kann die Kommunikation zwischen einem Ansichtsmodell und einer Ansicht auch durch die Bindungs-Engine und Benachrichtigungen über Eigenschaftsänderungen erreicht werden. Darüber hinaus kann die Kommunikation zwischen zwei Ansichtsmodellen auch durch die Übergabe von Daten während der Navigation erreicht werden.
In der mobilen eShopOnContainers-App wird verwendet, MessagingCenter
um in der Benutzeroberfläche als Reaktion auf eine Aktion in einer anderen Klasse zu aktualisieren. Daher werden Nachrichten im UI-Thread veröffentlicht, wobei Abonnenten die Nachricht im selben Thread empfangen.
Tipp
Marshal beim Ausführen von UI-Updates im UI-Thread. Wenn eine Nachricht, die von einem Hintergrundthread gesendet wird, zum Aktualisieren der Benutzeroberfläche erforderlich ist, verarbeiten Sie die Nachricht im UI-Thread im Abonnenten, indem Sie die Device.BeginInvokeOnMainThread
-Methode aufrufen.
Weitere Informationen finden MessagingCenter
Sie unter MessagingCenter.
Definieren einer Nachricht
MessagingCenter
-Nachrichten sind Zeichenfolgen, die zum Identifizieren von Nachrichten verwendet werden. Das folgende Codebeispiel zeigt die in der mobilen eShopOnContainers-App definierten Nachrichten:
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";
}
In diesem Beispiel werden Nachrichten mithilfe von Konstanten definiert. Der Vorteil dieses Ansatzes besteht darin, dass er Unterstützung für Typsicherheit zur Kompilierzeit und Refactoring bietet.
Veröffentlichen einer Nachricht
Herausgeber benachrichtigen Abonnenten einer Nachricht mit einer der MessagingCenter.Send
-Überladungen. Im folgenden Codebeispiel wird gezeigt, wie die AddProduct
-Nachricht veröffentlicht wird:
MessagingCenter.Send(this, MessageKeys.AddProduct, catalogItem);
In diesem Beispiel gibt die Send
Methode drei Argumente an:
- Mit dem ersten Argument wird die Absenderklasse angegeben. Die Absenderklasse muss von allen Abonnenten angegeben werden, die die Nachricht empfangen möchten.
- Das zweite Argument gibt die Nachricht an.
- Das dritte Argument gibt die Nutzlastdaten an, die an den Abonnenten gesendet werden sollen. In diesem Fall handelt es sich bei den Nutzlastdaten um eine
CatalogItem
Instanz.
Die Send
-Methode veröffentlicht die Nachricht sowie alle ihre Nutzdaten unter Verwendung eines Fire-and-Forget-Ansatzes. Daher wird die Nachricht auch dann gesendet, wenn für den Empfang der Nachricht keine Abonnenten registriert sind. Unter diesen Umständen wird die gesendete Nachricht ignoriert.
Hinweis
Die MessagingCenter.Send
-Methode kann generische Parameter verwenden, um zu steuern, wie Nachrichten übermittelt werden. Daher können mehrere Nachrichten, die eine Nachrichtenidentität gemeinsam nutzen, aber unterschiedliche Nutzdatentypen senden, von verschiedenen Abonnenten empfangen werden.
Abonnieren einer Nachricht
Abonnenten können sich registrieren, um eine Nachricht mit einer der MessagingCenter.Subscribe
-Überladungen zu empfangen. Im folgenden Codebeispiel wird veranschaulicht, wie die mobile eShopOnContainers-App die AddProduct
Nachricht abonniert und verarbeitet:
MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(
this, MessageKeys.AddProduct, async (sender, arg) =>
{
BadgeCount++;
await AddCatalogItemAsync(arg);
});
In diesem Beispiel abonniert die Methode die Subscribe
AddProduct
Nachricht und führt als Reaktion auf den Empfang der Nachricht einen Rückrufdelegat aus. Dieser Rückrufdelegat, der als Lambdaausdruck angegeben wird, führt Code aus, der die Benutzeroberfläche aktualisiert.
Tipp
Erwägen Sie die Verwendung unveränderlicher Nutzlastdaten. Versuchen Sie nicht, die Nutzlastdaten innerhalb eines Rückrufdelegats zu ändern, da mehrere Threads gleichzeitig auf die empfangenen Daten zugreifen können. In diesem Szenario sollten die Nutzdaten unveränderlich sein, um Parallelitätsfehler zu vermeiden.
Ein Abonnent muss möglicherweise nicht jede Instanz einer veröffentlichten Nachricht verarbeiten, und dies kann durch die generischen Typargumente gesteuert werden, die für die Subscribe
-Methode angegeben werden. In diesem Beispiel empfängt AddProduct
der Abonnent nur Nachrichten, die von der CatalogViewModel
Klasse gesendet werden, deren Nutzlastdaten eine CatalogItem
Instanz sind.
Abmelden von einer Nachricht
Abonnenten können Nachrichten kündigen, die Sie nicht mehr erhalten möchten. Dies wird mit einer der MessagingCenter.Unsubscribe
-Überladungen erreicht, wie im folgenden Codebeispiel gezeigt:
MessagingCenter.Unsubscribe<CatalogViewModel, CatalogItem>(this, MessageKeys.AddProduct);
In diesem Beispiel gibt die Unsubscribe
Methodensyntax die Typargumente wieder, die beim Abonnieren der AddProduct
Nachricht angegeben wurden.
Zusammenfassung
Die Xamarin.FormsMessagingCenter
Klasse implementiert das Veröffentlichungsabonnent-Muster, sodass nachrichtenbasierte Kommunikation zwischen Komponenten, die unannehlich sind, um eine Verknüpfung nach Objekt- und Typverweise zu ermöglichen. Dieser Mechanismus ermöglicht die Kommunikation zwischen Herausgebern und Abonnenten, ohne dass ein Verweis aufeinander besteht, und trägt dazu bei, die Abhängigkeiten zwischen Komponenten zu verringern. Zudem können Komponenten unabhängig voneinander entwickelt und getestet werden.