You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin中MessagingCenter重复触发问题求助

Xamarin Android中MessagingCenter重复触发问题的解决方案

问题根源

你的问题核心是MessagingCenter重复订阅:

  1. 每次点击停止追踪时,StopService方法都会重新订阅GPXBufferData事件,导致每次停止时该事件的回调执行次数累加。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 17:05:25