Partager via


Communication entre les composants faiblement couplés

Notes

Ce livre électronique a été publié au printemps 2017 et n’a pas été mis à jour depuis. Il y a beaucoup dans le livre qui reste précieux, mais une partie du matériel est obsolète.

Le modèle publier-s’abonner est un modèle de messagerie dans lequel les serveurs de publication envoient des messages sans avoir connaissance des destinataires, appelés des abonnés. De même, les abonnés écoutent des messages spécifiques, sans avoir connaissance des serveurs de publication.

Les événements dans .NET implémentent le modèle publication-abonnement et constituent l’approche la plus simple et la plus directe pour une couche de communication entre les composants si un couplage libre n’est pas nécessaire, tel qu’un contrôle et la page qui le contient. Toutefois, les durées de vie de l’auteur et de l’abonné sont couplées l’une à l’autre par des références d’objet, et le type d’abonné doit avoir une référence au type d’auteur. Cela peut créer des problèmes de gestion de la mémoire, en particulier lorsqu’il existe des objets de courte durée qui s’abonnent à un événement d’un objet statique ou de longue durée. Si le gestionnaire d’événements n’est pas supprimé, l’abonné est maintenu actif par la référence à celui-ci dans l’éditeur, ce qui empêche ou retarde le nettoyage de la mémoire de l’abonné.

Présentation de MessagingCenter

La Xamarin.FormsMessagingCenter classe implémente le modèle publier/s’abonner, ce qui permet à la communication basée sur les messages entre les composants qui ne sont pas pratiques de lier par références d’objet et de type. Ce mécanisme permet aux éditeurs et aux abonnés de communiquer sans qu’il y ait de référence l’un à l’autre, ce qui permet de réduire les dépendances entre les composants, tout en permettant aux composants d’être développés et testés indépendamment.

La classe MessagingCenter fournit la fonctionnalité publier-s’abonner de multidiffusion. Cela signifie que plusieurs serveurs de publication peuvent publient un seul message, et que plusieurs abonnés peuvent écouter le même message. La figure 4-1 illustre cette relation :

Fonctionnalité de publication-abonnement multidiffusion

Figure 4-1 : Fonctionnalité de publication-abonnement multidiffusion

Les serveurs de publication envoient des messages à l’aide de la méthode MessagingCenter.Send, alors que les abonnés écoutent les messages à l’aide de la méthode MessagingCenter.Subscribe. En outre, les abonnés peuvent également se désabonner des abonnements aux messages, si nécessaire, avec la méthode MessagingCenter.Unsubscribe.

En interne, la classe MessagingCenter utilise des références faibles. Cela signifie qu’elle ne conserve pas les objets actifs et leur permet d’être récupérés de la mémoire. Par conséquent, il ne doit être nécessaire de se désabonner d’un message que lorsqu’une classe ne souhaite plus recevoir le message.

L’application mobile eShopOnContainers utilise la MessagingCenter classe pour communiquer entre des composants faiblement couplés. L’application définit trois messages :

  • Le message AddProduct est publié par la classe CatalogViewModel lorsqu’un élément est ajouté au panier d’achat. En retour, la BasketViewModel classe s’abonne au message et incrémente le nombre d’éléments dans le panier en réponse. En outre, la BasketViewModel classe se désinscrit également de ce message.
  • Le Filter message est publié par la CatalogViewModel classe lorsque l’utilisateur applique un filtre de marque ou de type aux éléments affichés dans le catalogue. En retour, la classe s’abonne CatalogView au message et met à jour l’interface utilisateur afin que seuls les éléments correspondant aux critères de filtre soient affichés.
  • Le ChangeTab message est publié par la MainViewModel classe lorsque le CheckoutViewModel accède à la MainViewModel suite de la création et de l’envoi d’une nouvelle commande. En retour, la MainView classe s’abonne au message et met à jour l’interface utilisateur afin que l’onglet Mon profil soit actif pour afficher les commandes de l’utilisateur.

Notes

Bien que la classe MessagingCenter autorise la communication entre les classes faiblement couplées, elle n’offre pas la seule solution architecturale à ce problème. Par exemple, la communication entre un modèle d’affichage et une vue peut également être obtenue par le moteur de liaison et par le biais de notifications de modification de propriété. En outre, la communication entre deux modèles de vue peut également être obtenue en transmettant des données pendant la navigation.

Dans l’application mobile eShopOnContainers, MessagingCenter est utilisé pour effectuer une mise à jour dans l’interface utilisateur en réponse à une action se produisant dans une autre classe. Par conséquent, les messages sont publiés sur le thread d’interface utilisateur, les abonnés recevant le message sur le même thread.

Conseil

Marshalez vers le thread d’interface utilisateur lors de l’exécution de mises à jour de l’interface utilisateur. Si un message envoyé à partir d’un thread d’arrière-plan est nécessaire pour mettre à jour l’interface utilisateur, traitez le message sur le thread d’interface utilisateur dans l’abonné en appelant la méthode Device.BeginInvokeOnMainThread.

Pour plus d’informations sur MessagingCenter, consultez MessagingCenter.

Définition d’un message

Les messages MessagingCenter sont des chaînes utilisées pour identifier les messages. L’exemple de code suivant montre les messages définis dans l’application mobile 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";  
}

Dans cet exemple, les messages sont définis à l’aide de constantes. L’avantage de cette approche est qu’elle fournit la sécurité des types de compilation et la prise en charge de la refactorisation.

Publication d’un message

Les serveurs de publication informent les abonnés d’un message avec l’une des surcharges MessagingCenter.Send. L’exemple de code suivant illustre la publication du message AddProduct :

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

Dans cet exemple, la Send méthode spécifie trois arguments :

  • Le premier argument spécifie la classe de l’expéditeur. La classe d’expéditeur doit être spécifiée par tous les abonnés qui souhaitent recevoir le message.
  • Le deuxième argument spécifie le message.
  • Le troisième argument spécifie les données de charge utile à envoyer à l’abonné. Dans ce cas, les données de charge utile sont une CatalogItem instance.

La méthode Send va publier le message et toutes les données de sa charge utile en utilisant une approche « déclencher et oublier ». Le message est donc envoyé, même si aucun abonné n’est inscrit pour recevoir le message. Dans ce cas, le message envoyé est ignoré.

Notes

La méthode MessagingCenter.Send peut utiliser des paramètres génériques pour contrôler la façon dont les messages sont remis. Ainsi, plusieurs messages qui partagent une identité de message, mais qui envoient des types de données de charge utile différents, peuvent être reçus par différents abonnés.

Abonnement à un message

Les abonnés peuvent s’abonner pour recevoir un message à l’aide de l’une des surcharges MessagingCenter.Subscribe. L’exemple de code suivant montre comment l’application mobile eShopOnContainers s’abonne et traite le AddProduct message :

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

    await AddCatalogItemAsync(arg);  
});

Dans cet exemple, la Subscribe méthode s’abonne au AddProduct message et exécute un délégué de rappel en réponse à la réception du message. Ce délégué de rappel, spécifié en tant qu’expression lambda, exécute le code qui met à jour l’interface utilisateur.

Conseil

Envisagez d’utiliser des données de charge utile immuables. N’essayez pas de modifier les données de charge utile à partir d’un délégué de rappel, car plusieurs threads peuvent accéder aux données reçues simultanément. Dans ce scénario, les données de charge utile doivent être immuables pour éviter les erreurs d’accès concurrentiel.

Un abonné n’a peut-être pas besoin de gérer chaque instance d’un message publié, ce qui peut être contrôlé par les arguments de type générique spécifiés sur la méthode Subscribe. Dans cet exemple, l’abonné reçoit AddProduct uniquement les messages envoyés à partir de la classe, dont les CatalogViewModel données de charge utile sont une CatalogItem instance.

Désinscripment d’un message

Les abonnés peuvent se désinscrire des messages qu’ils ne souhaitent plus recevoir. Ceci est obtenu avec une des surcharges de MessagingCenter.Unsubscribe, comme illustré dans l’exemple de code suivant :

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

Dans cet exemple, la syntaxe de méthode Unsubscribe reflète les arguments de type spécifiés lors de l’abonnement pour recevoir le AddProduct message.

Résumé

La Xamarin.FormsMessagingCenter classe implémente le modèle publier/s’abonner, ce qui permet à la communication basée sur les messages entre les composants qui ne sont pas pratiques de lier par références d’objet et de type. Ce mécanisme permet aux éditeurs et aux abonnés de communiquer sans qu’il y ait de référence l’un à l’autre, ce qui permet de réduire les dépendances entre les composants, tout en permettant aux composants d’être développés et testés indépendamment.