Xamarin MessagingCenter问题:发送一次消息却多次接收
解决Xamarin MessagingCenter订阅重复接收消息的问题
这个问题我之前也碰到过,根源在于Popup页面的生命周期和普通导航页面不一样,导致你的订阅逻辑重复执行了。
问题分析
你在Page1的OnAppearing里订阅消息,OnDisappearing里取消订阅——但当你弹出Page2这个Popup页面时,底层的Page1并没有从导航栈中被移除,只是被Popup覆盖了,所以Page1的OnDisappearing方法根本不会被触发!
这就造成了:
- 第一次打开Popup,
Page1的OnDisappearing没执行,订阅没有被取消; - 关闭Popup时,
Page1的OnAppearing再次触发,又添加了一次订阅; - 现在同一个
Page1实例有两个相同的订阅,所以发送一次消息,回调会被执行两次。
你可以验证一下:在OnAppearing和OnDisappearing里各加一行日志,会发现打开Popup时OnDisappearing根本没跑。
解决方案
有两种靠谱的处理方式,根据你的需求选:
方案1:把订阅移到构造函数,取消订阅移到Dispose
因为页面的构造函数只会执行一次,这样从根源上避免重复订阅:
// Page1的构造函数 public Page1() { InitializeComponent(); // 在这里订阅,只执行一次 MessagingCenter.Subscribe<Page2, ParamType>(this, "PopUpData", async (sender, arg) => { Task.WaitAll(tasks.ToArray()); switch (arg.Tipo) { case 2: Console.WriteLine(" *********** msg received"); tasks.Add(Task.Run(() => ShareMap(arg))); break; case 3: tasks.Add(Task.Run(() => ShareEvent(arg))); break; case 6: tasks.Add(Task.Run(() => ShareImage(arg))); break; } }); } // 重写Dispose方法,页面销毁时取消订阅 protected override void Dispose(bool disposing) { if (disposing) { MessagingCenter.Unsubscribe<Page2, ParamType>(this, "PopUpData"); } base.Dispose(disposing); }
方案2:在OnAppearing里先取消再订阅
如果必须在页面出现时订阅,那每次订阅前先取消旧的订阅,确保不会重复:
protected override void OnAppearing() { base.OnAppearing(); // 先取消已有订阅,再添加新的 MessagingCenter.Unsubscribe<Page2, ParamType>(this, "PopUpData"); MessagingCenter.Subscribe<Page2, ParamType>(this, "PopUpData", async (sender, arg) => { Task.WaitAll(tasks.ToArray()); switch (arg.Tipo) { case 2: Console.WriteLine(" *********** msg received"); tasks.Add(Task.Run(() => ShareMap(arg))); break; case 3: tasks.Add(Task.Run(() => ShareEvent(arg))); break; case 6: tasks.Add(Task.Run(() => ShareImage(arg))); break; } }); } // OnDisappearing可以保留,但现在主要靠OnAppearing里的取消逻辑避免重复 protected override void OnDisappearing() { base.OnDisappearing(); MessagingCenter.Unsubscribe<Page2, ParamType>(this, "PopUpData"); }
额外提醒
MessagingCenter的订阅是基于订阅者实例、发送者类型、消息键三者的组合来区分的。同一个订阅者实例对同一个消息订阅多次,就会收到多次回调——这也是你遇到问题的核心原因,所以一定要确保订阅逻辑不会重复执行。
内容的提问来源于stack exchange,提问作者Éder Rocha
相关产品推荐
相关产品推荐

