Windows Phone 8.1 (RT) 应用程序,带有包含 67k 元素的 SQLite Db。工作缓慢

Windows Phone 8.1 (RT) app with SQLite Db which contains 67k elements. Works slowly

我为“Windows Phone 8.1”开发了一个应用程序,我正在使用一个包含 4700 个项目的数据库。在“Windows Store App 8.1/10 (Desktop/Tablet)”应用程序运行速度很快,但是“Windows Phone 8.1”可以看到“UI" 工作缓慢且滞后。这里是性能分析器的分析。

当应用程序启动方法“OnLaunching”时,我将数据从 sqlite 存储库加载到静态 属性“IEnumerable”中的静态 class。

await Task.Run(async () =>
    {
        if (InstanceMessageService.AllHolidays == null)
            {
                InstanceMessageService.AllHolidays = _repository.GetAll();
                InstanceMessageService.AllCountries = await Task.Run(() =>
                    InstanceMessageService.AllHolidays.GroupBy(holiday => holiday.Country)
                        .Select(x => x.First().Country)
                        .Select(s => new Country()
                        {
                            Title = s,
                            FirstLetter = s[0].ToString()
                        }).ToList()
                    );

                    if (!InstanceMessageService.AllHolidays.Any() || !InstanceMessageService.AllCountries.Any())
                    {
                        throw new Exception("Cannot load SQLite data"); 
                    }
                }
            });

这里是InstanceMessageService

public static class InstanceMessageService
{
    public static IEnumerable<Holiday> AllHolidays { get; set; } 
    public static IEnumerable<Country> AllCountries { get; set; }
    ...
}

现在 4700 个假期项目包含在静态属性(在内存中)和 171 个国家/地区项目。这不是我认为的好方法。

这是我的 CalendarsPage 的 ViewModel 代码。 CalendarsPage 提供今天、明天或从日历控件中选择的具体日期的假期数据。

public class CalendarPageViewModel : INotifyPropertyChanged
    
        public IEnumerable<Holiday> Holidays
        {
            get { return _holidays; }
            set
            {
                _holidays = value;
                OnPropertyChanged("Holidays");
            }
        }

        public ObservableCollection<Holiday> TodayHolidays
        {
            get { return _todayHolidays; }
            set
            {
                _todayHolidays = value;
                OnPropertyChanged("TodayHolidays");
            }
        }

        public ObservableCollection<Holiday> TomorrowHolidays
        {
            get { return _tomorrowHolidays; }
            set
            {
                _tomorrowHolidays = value;
                OnPropertyChanged("TomorrowHolidays");
            }
        }

        public ObservableCollection<Holiday> SelectedDateHoliday
        {
            get { return _selectedDateHoliday; }
            set
            {
                _selectedDateHoliday = value;
                OnPropertyChanged("SelectedDateHoliday");
            }
        }

        public CalendarPageViewModel()
        {
            Task task = InitCollections();
            InitCommands();
        }
     
       **// Slowly magic here**

        private async Task InitCollections()
        {
            Holidays = InstanceMessageService.AllHolidays;
            TomorrowHolidays = new ObservableCollection<Holiday>(await Task.Run(() => Holidays.Where(holiday => holiday.Date == DateTime.Now.AddDays(1).Date.ToString("MMM d")).Select(holiday => holiday)));
            TodayHolidays = new ObservableCollection<Holiday>(await Task.Run(() => Holidays.Where(holiday => holiday.Date == DateTime.Now.Date.ToString("MMM d")).Select(holiday => holiday)));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

存储库class代码

public class HolidaysRepository : IRepository<Holiday>
    {
        private readonly IDatabaseConnection _databaseConnection;
        public HolidaysRepository(IDatabaseConnection databaseConnection)
        {
            _databaseConnection = databaseConnection;
        }

        public List<Holiday> GetAll()
        {
            return _databaseConnection.Connection.Table<Holiday>().ToList();
        }

        public void AddOrUpdate(Holiday entity)
        {
            if (_databaseConnection.Connection.Table<Holiday>().FirstOrDefault(item => item.Id == entity.Id) !=
                null)
            {
                Update(entity);
            }
            else
            {
                Add(entity);
            }
        }

        public void Add(Holiday entity)
        {
            _databaseConnection.Connection.Insert(entity);
        }

        public void Update(Holiday entity)
        {
            _databaseConnection.Connection.Update(entity);
        }

        public void Delete(Holiday entity)
        {
            _databaseConnection.Connection.Delete(entity);
        }

        public void Clean()
        {
            _databaseConnection.Connection.DeleteAll<Holiday>();
        }
    }

这可能很重要,在我使用“Ninject”作为“ServiceLocator”的应用程序中。

如何提高应用程序的速度?如何减少使用的 RAM 量?如果 4700 个元素使应用程序变慢并且 UI 运行缓慢,那么我认为 67,000 个元素将没有足够的 RAM。

当加载大量数据花费的时间比您希望的要长时,最简单的解决方案通常是加载较少的数据。

您真的需要加载数据库中的所有假期吗?
你不能只加载你需要的特定日期吗?例如,默认加载今天和明天的任何假期,然后查找用户选择的任何其他特定日期。

如果您不需要所有假期但确实必须加载所有国家/地区,那么单独存储这些国家/地区的列表可能比加载所有假期只是为了提取国家/地区更快。

在数据库中查询数据时,您应该确保拥有适当的索引以加快查找速度。

查看数据上的索引可能也值得,这样您就可以直接从数据库中搜索它,而不是将其全部加载到您可能随后搜索的列表中。