Android 随着图表更新,用户界面速度迅速减慢

Android 随着图表更新,用户界面速度迅速减慢,android,xamarin.forms,bluetooth-lowenergy,syncfusion,Android,Xamarin.forms,Bluetooth Lowenergy,Syncfusion,我正在使用Xamarin.Forms开发一个移动应用程序。该应用程序连接到一个BLE设备,该设备每100毫秒传输16字节的数据。我正在用Syncfusion以条形图格式绘制数据 我可以连接到设备并接收数据而不会出现问题。但在很短的时间内,应用程序的性能开始显著下降。很快,它就完全停止了。显然,我在处理传入数据时出错了(除非是Syncfusion图表的性能问题) 简而言之,这就是我在应用程序中经历的过程 配对到设备(应用程序外部) 连接到设备(在应用程序中) 安装变速器 通过名为Spectrogr

我正在使用Xamarin.Forms开发一个移动应用程序。该应用程序连接到一个BLE设备,该设备每100毫秒传输16字节的数据。我正在用Syncfusion以条形图格式绘制数据

我可以连接到设备并接收数据而不会出现问题。但在很短的时间内,应用程序的性能开始显著下降。很快,它就完全停止了。显然,我在处理传入数据时出错了(除非是Syncfusion图表的性能问题)

简而言之,这就是我在应用程序中经历的过程

  • 配对到设备(应用程序外部)
  • 连接到设备(在应用程序中)
  • 安装变速器
  • 通过名为SpectrogramModel的
    模型处理传入数据
  • 在名为DataPage的
    视图
    中使用Syncfusion绘制数据图,该视图绑定到名为DataViewModel的
    视图模型
  • 在对设备进行配对并连接到设备后,我们将使用下面的方法来了解所有的细节。是否是
    设备.beginInvokeMainThread()
    调用最终开始阻止应用程序?此方法是从
    连接
    类调用的,该类引用了DataViewModel

    private void UpdateSpectrogramChart(object sender, EventArgs e)
        {
            DebugHelper.Message(Type.Method, "UpdateSpectrogramChart");
    
            _characteristic.ValueUpdated += (o, args) =>
            {
                var raw = args.Characteristic.Value;
    
                for (int i = 0; i < raw.Length; i++)
                {
                    Debug.WriteLine("Level[{0}] = {1}", i, raw[i]);
                }
    
                Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
                {
                    DataPageViewModel.Levels.Clear();
    
                    for (int i = SpectrogramModel.FrequencyOffset; i < raw.Length; i++)
                    {
                        if (SettingsViewModel.IsViewRawData)
                        {
                            DataPageViewModel.Title = "Raw data";
    
                            DataPageViewModel
                            .Levels
                            .Add(
                                new SpectrogramModel(
                                    raw[i],
                                    1 + (i - SpectrogramModel.FrequencyOffset))
                                    );
                        }
                        if (SettingsViewModel.IsViewProcessedData)
                        {
                            DataPageViewModel.Title = "Processed data";
    
                            DataPageViewModel
                            .Levels
                            .Add(
                                new SpectrogramModel(
                                    raw[i],
                                    1 + (i - SpectrogramModel.FrequencyOffset),
                                    i));
                        }
                    }
                });
            };
        }
    
    数据页如下所示

    public class SpectrogramModel
    {
        public SpectrogramModel(byte level, int frequency)
        {
            Level = level;
            Frequency = frequency;
        }
    
        public SpectrogramModel(byte level, int frequency, int index) : this(level, frequency)
        {
            Level = ProcessRawLevel(level, index);
        }
    
        private double ProcessRawLevel(byte b, int index)
        {
            double multiplier = 0.75;
            double val = b;
            val *= multiplier;
            return val;
        }
    
        public static readonly int FrequencyOffset = 4;
    
        ...
    
    <chart:SfChart>
    
            <chart:SfChart.Title>
                <chart:ChartTitle
                            Text="{Binding Title}">
                </chart:ChartTitle>
            </chart:SfChart.Title>
    
            <chart:SfChart.PrimaryAxis>
    
                <chart:CategoryAxis>
                </chart:CategoryAxis>
    
            </chart:SfChart.PrimaryAxis>
    
            <chart:SfChart.SecondaryAxis>
    
                <chart:NumericalAxis
                    Minimum="20" 
                    Maximum="100">
                </chart:NumericalAxis>
    
            </chart:SfChart.SecondaryAxis>
    
            <chart:SfChart.Series>
    
                <chart:ColumnSeries ItemsSource="{Binding Levels}" XBindingPath="Frequency" YBindingPath="Level"/>
    
            </chart:SfChart.Series>
    
        </chart:SfChart>
    
    public void InitTimers()
        {
            DebugHelper.Message(Type.Method, "InitTimers");
            int SECOND = 1000 * 2;
            SpectrogramChartTimer = new Timer();
            SpectrogramChartTimer.Elapsed += new ElapsedEventHandler(UpdateSpectrogramChart);
            SpectrogramChartTimer.Interval = SECOND;
        }
    
    我将对
    UpdateSpectrogramChart()
    方法的调用包装在(清除)失败的尝试中,以减少性能下降

    为了完整起见,这里是设置从BLE设备接收的方法的方法体

    public async Task ReceiveFromGattCharacteristic(string service, string characteristic, string descriptor = null)
        {
            DebugHelper.Message(Type.Method, "ReceiveFromGattCharacteristic");
    
            bleAdapter.DeviceConnected += async (s, e) =>
            {
                try
                {
                    DebugHelper.Message(Type.Info, "bleAdapter.DeviceConected += async (s, e) ...");
    
                    string[] deviceInfo = { e.Device.Name, e.Device.Id.ToString() };
    
                    // Connect to service
                    try
                    {
                        DebugHelper.Message(Type.Info, "Connecting to service...");
                        _service = await e.Device.GetServiceAsync(Guid.Parse(service));
                        DebugHelper.Message(Type.Info, "OK");
                    }
    
                    catch (Exception)
                    {
                        DebugHelper.Error(ErrorType.GATT, "Could not connect to service");
                    }
    
                    // Connect to characteristic
                    try
                    {
                        DebugHelper.Message(Type.Info, "Connecting to characteristic...");
                        _characteristic = await _service.GetCharacteristicAsync(Guid.Parse(characteristic));
                        DebugHelper.Message(Type.Info, "OK");
                    }
    
                    catch (Exception)
                    {
                        DebugHelper.Error(ErrorType.GATT, "Could not connect to characteristic");
                    }
    
                    await ConfigureSpectrogram(UpdateFrequency.High, 0x1);
    
                    try
                    {
                        await _characteristic.StartUpdatesAsync();
                    }
    
                    catch
                    {
                        DebugHelper.Error(ErrorType.GATT, "Error starting UpdatesAsync");
                    }
    
                    _characteristic.ValueUpdated += (o, args) =>
                    {
                        var raw = args.Characteristic.Value;
    
                        for (int i = 4; i < raw.Length; i++)
                        {
                            Debug.WriteLine("Level[{0}] = {1}", i - 4, raw[i]);
                        }
                    };
                }
    
                catch (Exception)
                {
                    DebugHelper.Error(ErrorType.GATT, "Error in ReceiveFromGattCharacteristic");
                }
            };
        }
    
    公共异步任务ReceiveFromGattCharacteristic(字符串服务,字符串特征,字符串描述符=null) { Message(Type.Method,“ReceiveFromGattCharacteristic”); bleAdapter.DeviceConnected+=异步(s,e)=> { 尝试 { 消息(Type.Info,“bleAdapter.deviceconnected+=async(s,e)…”; 字符串[]deviceInfo={e.Device.Name,e.Device.Id.ToString()}; //连接到服务 尝试 { 消息(Type.Info,“连接到服务…”); _service=wait e.Device.GetServiceAsync(Guid.Parse(service)); DebugHelper.Message(Type.Info,“OK”); } 捕获(例外) { DebugHelper.Error(ErrorType.GATT,“无法连接到服务”); } //连接到特征 尝试 { 消息(Type.Info,“连接到特征…”); _characteristic=wait_service.GetCharacteristicAsync(Guid.Parse(characteristic)); DebugHelper.Message(Type.Info,“OK”); } 捕获(例外) { DebugHelper.Error(ErrorType.GATT,“无法连接到特征”); } 等待配置频谱图(UpdateFrequency.High,0x1); 尝试 { wait_characteristic.StartUpdatesAsync(); } 抓住 { DebugHelper.Error(ErrorType.GATT,“启动更新同步时出错”); } _characteristic.ValueUpdated+=(o,args)=> { var raw=args.Characteristic.Value; for(int i=4;i
    好吧,我不确定这是否真的可以作为一个答案,但我似乎已经解决了这个问题,尽管我不能肯定这为什么解决了这个问题

    在摆弄了一个
    BackgroundWorker
    (可能是因为我不擅长使用它)之后,我修改了代码,并将
    模型的更新和
    视图的更新直接移动到
    ReceiveFromGattCharacteristic()
    ,方法,而不是使用单独的方法更新
    模型
    视图
    ,如下所示:

    public void ReceiveFromGattCharacteristic(string service, string characteristic, string descriptor = null)
        {
            DebugHelper.Message(Type.Method, "ReceiveFromGattCharacteristic");
    
            bleAdapter.DeviceConnected += async (s, e) =>
            {
                try
                {
                    DebugHelper.Message(Type.Info, "bleAdapter.DeviceConected += async (s, e) ...");
    
                    string[] deviceInfo = { e.Device.Name, e.Device.Id.ToString() };
    
                    // Connect to service
                    try
                    {
                        DebugHelper.Message(Type.Info, "Connecting to service...");
                        _service = await e.Device.GetServiceAsync(Guid.Parse(service));
                        DebugHelper.Message(Type.Info, "OK");
                    }
    
                    catch (Exception)
                    {
                        DebugHelper.Error(ErrorType.GATT, "Could not connect to service");
                    }
    
                    // Connect to characteristic
                    try
                    {
                        DebugHelper.Message(Type.Info, "Connecting to characteristic...");
                        _characteristic = await _service.GetCharacteristicAsync(Guid.Parse(characteristic));
                        DebugHelper.Message(Type.Info, "OK");
                    }
    
                    catch (Exception)
                    {
                        DebugHelper.Error(ErrorType.GATT, "Could not connect to characteristic");
                    }
    
                    await ConfigureSpectrogram(UpdateFrequency.High, 0x1);
    
                    try
                    {
                        await _characteristic.StartUpdatesAsync();
                    }
    
                    catch
                    {
                        DebugHelper.Error(ErrorType.GATT, "Error starting UpdatesAsync");
                    }
                    // ADDITION
                    _characteristic.ValueUpdated += (o, args) =>
                    {
                        var raw = args.Characteristic.Value;
    
                        Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
                        {
                            DataPageViewModel.Levels.Clear();
    
                            for (int i = Models.Spectrogram.FrequencyOffset; i < raw.Length; i++)
                            {
                                if (SettingsViewModel.IsViewRawData)
                                {
                                    DataPageViewModel.Title = "Raw data";
    
                                    DataPageViewModel
                                    .Levels
                                    .Add(
                                        new Models.Spectrogram(
                                            raw[i],
                                            1 + (i - Models.Spectrogram.FrequencyOffset))
                                            );
                                }
    
                                if (SettingsViewModel.IsViewProcessedData)
                                {
                                    DataPageViewModel.Title = "Processed data";
    
                                    DataPageViewModel
                                    .Levels
                                    .Add(
                                        new Models.Spectrogram(
                                            raw[i],
                                            1 + (i - Models.Spectrogram.FrequencyOffset),
                                            i));
                                }
                            }
                        });
                    };
                }
                // END OF ADDITION
    
                catch (Exception)
                {
                    DebugHelper.Error(ErrorType.GATT, "Error in ReceiveFromGattCharacteristic");
                }
            };
        }
    
    public void ReceiveFromGattCharacteristic(字符串服务,字符串特征,字符串描述符=null)
    {
    Message(Type.Method,“ReceiveFromGattCharacteristic”);
    bleAdapter.DeviceConnected+=异步(s,e)=>
    {
    尝试
    {
    消息(Type.Info,“bleAdapter.deviceconnected+=async(s,e)…”;
    字符串[]deviceInfo={e.Device.Name,e.Device.Id.ToString()};
    //连接到服务
    尝试
    {
    消息(Type.Info,“连接到服务…”);
    _service=wait e.Device.GetServiceAsync(Guid.Parse(service));
    DebugHelper.Message(Type.Info,“OK”);
    }
    捕获(例外)
    {
    DebugHelper.Error(ErrorType.GATT,“无法连接到服务”);
    }
    //连接到特征
    尝试
    {
    消息(Type.Info,“连接到特征…”);
    _characteristic=wait_service.GetCharacteristicAsync(Guid.Parse(characteristic));
    DebugHelper.Message(Type.Info,“OK”);
    }
    捕获(例外)
    {
    DebugHelper.Error(ErrorType.GATT,“无法连接到特征”);
    }
    等待确认
    
    public void ReceiveFromGattCharacteristic(string service, string characteristic, string descriptor = null)
        {
            DebugHelper.Message(Type.Method, "ReceiveFromGattCharacteristic");
    
            bleAdapter.DeviceConnected += async (s, e) =>
            {
                try
                {
                    DebugHelper.Message(Type.Info, "bleAdapter.DeviceConected += async (s, e) ...");
    
                    string[] deviceInfo = { e.Device.Name, e.Device.Id.ToString() };
    
                    // Connect to service
                    try
                    {
                        DebugHelper.Message(Type.Info, "Connecting to service...");
                        _service = await e.Device.GetServiceAsync(Guid.Parse(service));
                        DebugHelper.Message(Type.Info, "OK");
                    }
    
                    catch (Exception)
                    {
                        DebugHelper.Error(ErrorType.GATT, "Could not connect to service");
                    }
    
                    // Connect to characteristic
                    try
                    {
                        DebugHelper.Message(Type.Info, "Connecting to characteristic...");
                        _characteristic = await _service.GetCharacteristicAsync(Guid.Parse(characteristic));
                        DebugHelper.Message(Type.Info, "OK");
                    }
    
                    catch (Exception)
                    {
                        DebugHelper.Error(ErrorType.GATT, "Could not connect to characteristic");
                    }
    
                    await ConfigureSpectrogram(UpdateFrequency.High, 0x1);
    
                    try
                    {
                        await _characteristic.StartUpdatesAsync();
                    }
    
                    catch
                    {
                        DebugHelper.Error(ErrorType.GATT, "Error starting UpdatesAsync");
                    }
                    // ADDITION
                    _characteristic.ValueUpdated += (o, args) =>
                    {
                        var raw = args.Characteristic.Value;
    
                        Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
                        {
                            DataPageViewModel.Levels.Clear();
    
                            for (int i = Models.Spectrogram.FrequencyOffset; i < raw.Length; i++)
                            {
                                if (SettingsViewModel.IsViewRawData)
                                {
                                    DataPageViewModel.Title = "Raw data";
    
                                    DataPageViewModel
                                    .Levels
                                    .Add(
                                        new Models.Spectrogram(
                                            raw[i],
                                            1 + (i - Models.Spectrogram.FrequencyOffset))
                                            );
                                }
    
                                if (SettingsViewModel.IsViewProcessedData)
                                {
                                    DataPageViewModel.Title = "Processed data";
    
                                    DataPageViewModel
                                    .Levels
                                    .Add(
                                        new Models.Spectrogram(
                                            raw[i],
                                            1 + (i - Models.Spectrogram.FrequencyOffset),
                                            i));
                                }
                            }
                        });
                    };
                }
                // END OF ADDITION
    
                catch (Exception)
                {
                    DebugHelper.Error(ErrorType.GATT, "Error in ReceiveFromGattCharacteristic");
                }
            };
        }
    
    Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
                {
                    DataPageViewModel.Levels.Clear();
    
    Chart.SuspendSeriesNotification();
    
                    for (int i = SpectrogramModel.FrequencyOffset; i < raw.Length; i++)
                    {
                        if (SettingsViewModel.IsViewRawData)
                        {
                            DataPageViewModel.Title = "Raw data";
    
                            DataPageViewModel
                            .Levels
                            .Add(
                                new SpectrogramModel(
                                    raw[i],
                                    1 + (i - SpectrogramModel.FrequencyOffset))
                                    );
                        }
                        if (SettingsViewModel.IsViewProcessedData)
                        {
                            DataPageViewModel.Title = "Processed data";
    
                            DataPageViewModel
                            .Levels
                            .Add(
                                new SpectrogramModel(
                                    raw[i],
                                    1 + (i - SpectrogramModel.FrequencyOffset),
                                    i));
                        }
                    }
    Chart.ResumeSeriesNotification();
                });