Xamarin中MessagingCenter重复触发问题求助
Xamarin Android中MessagingCenter重复触发问题的解决方案
问题根源
你的问题核心是MessagingCenter重复订阅:
- 每次点击停止追踪时,
StopService方法都会重新订阅GPXBufferData事件,导致每次停止时该事件的回调执行次数累加。 GPSLocationService.Run方法每次启动服务时,都会新增一个ServiceStopped的订阅,停止服务时所有历史订阅都会被触发。
解决方案
1. 统一页面级订阅时机,避免重复订阅
将GPXBufferData的订阅移到页面生命周期方法中,确保只订阅一次,页面销毁时自动取消:
protected override void OnAppearing() { base.OnAppearing(); // 页面显示时订阅,仅执行一次 MessagingCenter.Subscribe<App, List<Location>>(this, "GPXBufferData", (sender, args) => { RawGPXData = args; Generate_CreateGPX_File(RawGPXData); RawBufferToJsonString = GPXParse.GenerateJSON_GPXPoints(RawGPXData); Console.WriteLine("---------------------------------------------------------------:RawBufferToJsonString: " + RawBufferToJsonString); PromptForSubmission_GPXPoints_API(); }); } protected override void OnDisappearing() { base.OnDisappearing(); // 页面隐藏时取消订阅,防止内存泄漏和重复触发 MessagingCenter.Unsubscribe<App, List<Location>>(this, "GPXBufferData"); }
同时修改StopService方法,移除里面的订阅逻辑:
private void StopService() { var stopServiceMessage = new StopServiceMessage(); Console.WriteLine("--------------------------------------------------------------------------"); MessagingCenter.Send(stopServiceMessage, "ServiceStopped"); Preferences.Set("LocationServiceRunning", false); Console.WriteLine("---------------------------------------------------------------Location service stopped. preferences saved"); }
2. 清理服务端重复订阅
修改GPSLocationService.Run方法,确保每次启动服务前先取消旧的ServiceStopped订阅,处理完后再自动取消当前订阅:
public async Task Run(CancellationToken token) { int ObjCount = 0; // 先取消之前的订阅,避免重复触发 MessagingCenter.Unsubscribe<StopServiceMessage>(this, "ServiceStopped"); MessagingCenter.Subscribe<StopServiceMessage>(this, "ServiceStopped", message => { if (GPSBufferObj != null) { Device.BeginInvokeOnMainThread(() => { MessagingCenter.Send<App, List<Location>>((App)Xamarin.Forms.Application.Current, "GPXBufferData", GPSBufferObj); }); } // 处理完成后立即取消订阅,防止下次启动重复触发 MessagingCenter.Unsubscribe<StopServiceMessage>(this, "ServiceStopped"); }); await Task.Run(async () => { // 这里放置你的GPS实时追踪逻辑(原代码中可能遗漏了核心追踪逻辑) while (!token.IsCancellationRequested) { // 示例:获取位置并添加到缓冲区 var location = await CrossGeolocator.Current.GetPositionAsync(); GPSBufferObj.Add(location); await Task.Delay(1000); } }, token); }
额外检查点
- 确认
StartListening和StopListening方法中,CrossGeolocator的位置监听没有重复注册的情况,避免位置数据重复收集。 - 确保
IsTracking状态在启停时正确切换,防止服务重复启动。
内容的提问来源于stack exchange,提问作者tlf
相关产品推荐
相关产品推荐

