发布订阅模式是一种消息传递模式,其中发布者发送消息而不知道任何接收者(称为订阅者)。 类似地,订阅者听取特定的消息,而不了解任何发布者。
.NET中的事件实现了发布 - 订阅模式,并且是不需要松散耦合的组件之间的通信层的最简单和直接的方法,例如控件和包含它的页面。 然而,发布者和订阅者的生命周期通过对象引用彼此耦合,订户类型必须具有对发布者类型的引用。 这可以创建内存管理问题,特别是当存在订阅静态或长寿命对象的事件的短暂的对象时。 如果事件处理程序没有被删除,则订阅者将通过在发布者中引用它来保持活动状态,这将防止或延迟用户的垃圾回收。
消息中心简介
Xamarin.Forms MessagingCenter类实现了发布 - 订阅模式,允许不便于通过对象和类型引用链接的组件之间的基于消息的通信。 这种机制允许发布者和订阅者在不相互引用的情况下通信,有助于减少组件之间的依赖关系,同时还允许组件进行独立开发和测试。
MessagingCenter类提供组播发布 - 订阅功能。 这意味着可以有多个发布者发布单个消息,并且可以有多个订阅者监听相同的消息。 图4-1说明了这种关系:
图4-1:组播发布 - 订阅功能
发布者使用MessagingCenter.Send方法发送消息,而订阅者使用MessagingCenter.Subscribe方法监听消息。 此外,订阅者还可以使用MessagingCenter.Unsubscribe方法取消订阅邮件订阅(如果需要)。
在内部,MessagingCenter类使用弱引用。 这意味着它不会保持对象活着,并且允许它们被垃圾收集。 因此,当班级不再希望收到消息时,只需要取消订阅消息。
eShopOnContainers移动应用程序使用MessagingCenter类在松散耦合的组件之间进行通信。 应用程序定义了三条消息:
· 当将Item添加到购物篮时,AddProduct消息由CatalogViewModel类发布。 作为回报,BasketViewModel类订阅消息,并增加购物篮中的项目数量作为响应。 此外,BasketViewModel类也取消订阅此消息。
· 当用户向目录中显示的项目应用品牌或类型过滤器时,由CatalogViewModel类发布过滤器消息。 作为回报,CatalogView类订阅消息并更新UI,以便仅显示与过滤条件匹配的项目。
· 当成功创建和提交新订单后,当CheckoutViewModel导航到MainViewModel时,ChangeTab消息由MainViewModel类发布。 作为回报,MainView类订阅消息并更新UI,以便我的配置文件选项卡处于活动状态,以显示用户的订单。
注意:虽然MessagingCenter类允许在松散耦合的类之间进行通信,但它不提供此问题的唯一架构解决方案。 例如,视图模型和视图之间的通信也可以通过绑定引擎和通过属性更改通知来实现。 另外,两个视图模型之间的通信也可以通过在导航期间传递数据来实现。
在eShopOnContainers移动应用程序中,MessagingCenter用于在UI中更新以响应另一个类中发生的操作。 因此,消息在UI线程上发布,订阅者在同一个线程上接收消息。
? 提示:执行UI更新时,向UI线程的元组。 如果需要从后台线程发送的消息来更新UI,则可以通过调用Device.BeginInvokeOnMainThread方法在订阅者的UI线程上处理消息。
有关MessagingCenter的更多信息,请参阅Xamarin开发人员中心的MessagingCenter。
定义消息
MessagingCenter消息是用于标识消息的字符串。 以下代码示例显示了eShopOnContainers移动应用程序中定义的消息:
点击(此处)折叠或打开
-
public class MessengerKeys
-
{
-
// Add product to basket
-
public const string AddProduct = "AddProduct";
-
-
// Filter
-
public const string Filter = "Filter";
-
-
// Change selected Tab programmatically
-
public const string ChangeTab = "ChangeTab";
- }
在这个例子中,使用常量来定义消息。 这种方法的优点是它提供了编译时类型的安全和重构支持。
发表消息
发布商通过MessagingCenter.Send重载之一通知订阅者消息。 以下代码示例演示如何发布AddProduct消息:
MessagingCenter.Send(this, MessengerKeys.AddProduct, catalogItem);
在这个例子中,Send方法指定三个参数:
· 第一个参数指定发件人类。 发件人类必须由希望接收邮件的任何用户指定。
· 第二个参数指定消息。
· 第三个参数指定要发送给用户的有效载荷数据。 在这种情况下,有效载荷数据是CatalogItem实例。
发送方法将使用火灾忘记的方式发布消息及其有效载荷数据。 因此,即使没有订阅者注册接收消息,也会发送该消息。 在这种情况下,发送的消息将被忽略。
注意:MessagingCenter.Send方法可以使用通用参数来控制邮件的传递方式。 因此,不同的订户可以接收到共享消息身份但发送不同有效载荷数据类型的多个消息。
订阅消息
订阅者可以注册以使用MessagingCenter之一接收消息。订阅超载。 以下代码示例演示了eShopOnContainers移动应用程序如何订阅并处理AddProduct消息:
点击(此处)折叠或打开
-
MessagingCenter.Subscribe(
-
this, MessageKeys.AddProduct, async (sender, arg) =>
-
{
-
BadgeCount++;
-
-
await AddCatalogItemAsync(arg);
- });
在此示例中,Subscribe方法订阅AddProduct消息,并响应于接收到消息执行回调委托。 此回调委托,指定为lambda表达式,执行更新UI的代码。
? 提示:考虑使用不变的有效载荷数据。 不要尝试从回调委托中修改有效负载数据,因为多个线程可能会同时访问接收到的数据。 在这种情况下,有效载荷数据应该是不可变的,以避免并发错误。
用户可能不需要处理已发布消息的每个实例,并且可以通过在Subscribe方法中指定的通用类型参数来控制。 在此示例中,订阅者将只接收从CatalogViewModel类发送的AddProduct消息,该类的负载数据是CatalogItem实例。
取消订阅消息
订阅者可以取消订阅他们不想再收到的消息。 这是通过MessagingCenter之一实现的。请注意重载,如以下代码示例所示:
点击(此处)折叠或打开
- MessagingCenter.Unsubscribe(this, MessengerKeys.AddProduct);
在此示例中,Unsubscribe方法语法反映了订阅接收AddProduct消息时指定的类型参数。
概要
Xamarin.Forms MessagingCenter类实现了发布 - 订阅模式,允许不便于通过对象和类型引用链接的组件之间的基于消息的通信。 这种机制允许发布者和订阅者在不相互引用的情况下通信,有助于减少组件之间的依赖关系,同时还允许组件进行独立开发和测试。