首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MessagingCenter多次射击的问题

MessagingCenter多次射击的问题
EN

Stack Overflow用户
提问于 2022-10-27 19:00:37
回答 1查看 51关注 0票数 0

我到处寻找解决问题的办法。我注意到,在我的安卓应用程序中,每当我从<button Clicked="GPSToggle_Clicked">中触发一个事件时,由于某种原因,它会增加调用我的方法的次数。所以,在我编译并在手机上加载这个之后,我点击了我的"GPSToggle_Clicked“按钮,然后停止再按那个按钮。在第一个“停止”中,我将得到以下输出的一个实例:

代码语言:javascript
复制
    ---------------------------------------------------------------Attempting string parsing
---------------------------------------------------------------Sending string to SubmitGeneratedGPX
---------------------------------------------------------------path: /storage/emulated/0/Download/GPX/2022-10-27-02-44-06.gpx
---------------------------------------------------------------GPX File creation success
---------------------------------------------------------------:RawBufferToJsonString: [{"Timestamp":"2022-10-27T18:43:52.849+00:00","Latitude":41.5263818,"Longitude":-81.6507923,"Altitude":153.29998779296875,"Accuracy":20.0,"VerticalAccuracy":1.7990270853042603,"Speed":null,"Course":null,"IsFromMockProvider":false,"AltitudeReferenceSystem":2},{"Timestamp":"2022-10-27T18:43:53.696+00:00","Latitude":41.5263819,"Longitude":-81.6507921,"Altitude":153.29998779296875,"Accuracy":20.0,"VerticalAccuracy":1.7697961330413818,"Speed":null,"Course":null,"IsFromMockProvider":false,"AltitudeReferenceSystem":2},{"Timestamp":"2022-10-27T18:43:54.526+00:00","Latitude":41.5263819,"Longitude":-81.6507921,"Altitude":153.29998779296875,"Accuracy":20.0,"VerticalAccuracy":1.7697961330413818,"Speed":null,"Course":null,"IsFromMockProvider":false,"AltitudeReferenceSystem":2},{"Timestamp":"2022-10-27T18:43:55.374+00:00","Latitude":41.5263819,"Longitude":-81.6507921,"Altitude":153.29998779296875,"Accuracy":20.0,"VerticalAccuracy":1.7697961330413818,"Speed":null,"Course":null,"IsFromMockProvider":false,"AltitudeReferenceSystem":2},{"Timestamp":"2022-10-27T18:43:56.21+00:00","Latitude":41.5263811,"Longitude":-81.650792,"Altitude":153.29998779296875,"Accuracy":20.0,"VerticalAccuracy":1.7160584926605225,"Speed":null,"Course":null,"IsFromMockProvider":false,"AltitudeReferenceSystem":2}]

每次在应用程序上单击start/stop时,我都会得到输出中的实时数据乘以自上次编译以来启动/停止的次数。

启动的主应用程序页面按钮事件:

代码语言:javascript
复制
private async void GPSToggle_Clicked(object sender, EventArgs e)
    {
        var LocationPermissionStatus = await Xamarin.Essentials.Permissions.RequestAsync<Xamarin.Essentials.Permissions.LocationAlways>();
        var FileReadPermissionStatus = await Xamarin.Essentials.Permissions.RequestAsync<Xamarin.Essentials.Permissions.StorageRead>();
        var FileWritePermissionStatus = await Xamarin.Essentials.Permissions.RequestAsync<Xamarin.Essentials.Permissions.StorageWrite>();
        if(LocationPermissionStatus == Xamarin.Essentials.PermissionStatus.Denied)
        {
            // TODO
            return;
        }
        
        // run if device is android
        if(Device.RuntimePlatform == Device.Android)
        {
            if (!CrossGeolocator.Current.IsGeolocationAvailable || !CrossGeolocator.Current.IsGeolocationEnabled)
            {
                // gps is not enabled, throw alert
                Console.WriteLine("---------------------------------------------------------------GPS is DISABLED");
                await DisplayAlert("Error", "GPS is not enabled. You must enable GPS to use this feature", "Ok");
            }
            else
            {
                // set our IsTracking = true flag
                if (!IsTracking)
                {
                    // start background listening for GPS
                    await StartListening();
                    Console.WriteLine("---------------------------------------------------------------Listening: " + CrossGeolocator.Current.IsListening);
                    StartService();
                    Console.WriteLine("---------------------------------------------------------------Service initiated");
                    IsTracking = true;
                    Console.WriteLine("---------------------------------------------------------------Tracking initiated");
                    GPSToggle.Text = "Stop Tracking";
                }
                else
                {
                    //
                    // verify that the submittal wasn't done in error, before stopping services and submitting data
                    bool DoneInError = await DisplayAlert("Finish?", "Are you sure you want to stop services and submit?", "No", "Yes");
                    if (!DoneInError)
                    {
                        await StopListening();
                        Console.WriteLine("---------------------------------------------------------------listening:" + CrossGeolocator.Current.IsListening);
                        IsTracking = false;
                        Console.WriteLine("---------------------------------------------------------------Tracking ceased");
                        // stop the gps service
                        StopService();
                        Console.WriteLine("---------------------------------------------------------------Service ceased");
                        // stop the background listening for gps
                        Console.WriteLine("---------------------------------------------------------------Attempt GPX parse from buffer obj");

                        GPSToggle.Text = "Start Tracking";
                    }
                }
            }
        }
    }

具体而言,这一行:

代码语言:javascript
复制
StartService();

在同一个类(特别是MessagingCenter.Send<> )中触发此方法,该类启动我的前台服务,将gps数据记录到缓冲区中:

代码语言:javascript
复制
private void StartService()
    {            
        var startServiceMessage = new StartServiceMessage();
        MessagingCenter.Send(startServiceMessage, "ServiceStarted");
        Preferences.Set("LocationServiceRunning", true);
        StatusLabel.Text = "Location service has been started";
        Console.WriteLine("---------------------------------------------------------------location service has been started. preferences saved");
    }

代码语言:javascript
复制
StopService(); 

触发此方法以停止服务并从前台检索gps缓冲区数据到主线程:

代码语言:javascript
复制
private void StopService()
    {
        var stopServiceMessage = new StopServiceMessage();
        MessagingCenter.Unsubscribe<App, List<Location>>(this, "GPXBufferData");
        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();
        });
        Console.WriteLine("--------------------------------------------------------------------------");
        MessagingCenter.Send(stopServiceMessage, "ServiceStopped");
        Preferences.Set("LocationServiceRunning", false);
        Console.WriteLine("---------------------------------------------------------------Location service stopped. preferences saved");
    }

在上面的片段中,在GPSLocationService.cs文件中订阅了这一行:

代码语言:javascript
复制
MessagingCenter.Send(stopServiceMessage, "ServiceStopped");

这是与此相关的GPSLocationService.cs文件的一部分:

代码语言:javascript
复制
public async Task Run(CancellationToken token)
    {
        int ObjCount = 0;
        await Task.Run(async () => {
            // if the task was stopped
            // check the buffer for data, if data, send to GPXGenerator
            MessagingCenter.Subscribe<StopServiceMessage>(this, "ServiceStopped",
            message =>
            {
                if (GPSBufferObj != null)
                {
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        MessagingCenter.Unsubscribe<App, List<Location>>((App)Xamarin.Forms.Application.Current, "GPXBufferData");
                        MessagingCenter.Send<App, List<Location>>((App)Xamarin.Forms.Application.Current, "GPXBufferData", GPSBufferObj);

                    });
                }
            });

            return;
        }, token);
    }

我相信我已经找到了这个问题的起点。在我的StopService()方法中,我有以下一行(只是为了跟踪我在缓冲区中的位置),它只被发送到输出一次。

代码语言:javascript
复制
Console.WriteLine("--------------------------------------------------------------------------");

但是,如果我将这一行放在我的GPSLocationService.cs文件的粘贴部分中,我将得到递增的输出。我倾向于将嵌套的任务作为问题,我用这个示例repro:https://github.com/jfversluis/XFBackgroundLocationSample编写了这个不符合逻辑的代码

EN

回答 1

Stack Overflow用户

发布于 2022-10-27 23:27:37

您的代码中没有有MessagingCenter.Unsubscribe<StopServiceMessage> anywhereStopServiceMessage是您正在累积订阅的内容。

您需要确保Unsubscribe取消订阅以前订阅的实例。在我看来,GPSLocationService有多个实例。在这种情况下,this不再引用原始实例。取消订阅不会做任何事情,除非您有最初订阅的this

如果是这样,则创建一个GPSLocationService实例一次,并将其存储在一个静态变量中。再用一次。开始/停止它,但不要丢弃它。

或者,如果您只想从每个订阅中获得一次消息,那么在收到每条消息后立即取消订阅:

代码语言:javascript
复制
MessagingCenter.Subscribe<StopServiceMessage>(this, "ServiceStopped",
  message =>
  {
    MessagingCenter.Unsubscribe<StopServiceMessage>(this, "ServiceStopped");
    ... your code ...
  });

在任何有订阅的地方都使用相同的模式(除非像Jason建议的那样,在app开始时只订阅一次)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74227049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档