Виртуализация данных ListView и GridView

Примечание.
Дополнительные сведения см. в разделе //build/session Резкое увеличение производительности при взаимодействии пользователей с большими объемами данных в GridView и ListView.

Повышение производительности ListView и GridView с помощью виртуализации данных. Сведения о виртуализации пользовательского интерфейса, сокращении элементов и постепенном обновлении элементов см. в разделе "Оптимизация производительности ListView и GridView" для WinUI.

Метод виртуализации данных необходим для набора данных, который так велик, что он не может или не должен храниться в памяти одновременно. Вы загружаете начальную часть в память (из локального диска, сети или облака) и применяете виртуализацию пользовательского интерфейса к этому частичному набору данных. Позже данные можно загружать постепенно или из произвольных точек в наборе основных данных (случайный доступ) по запросу. Является ли виртуализация данных подходящей для вас, зависит от многих факторов.

  • Размер набора данных
  • Размер каждого элемента
  • Источник набора данных (локальный диск, сеть или облако)
  • Общее потребление памяти приложения WinUI

Примечание Помните, что функция включена по умолчанию для ListView и GridView, в которых отображаются временные визуальные элементы заполнителя во время быстрого сдвига или прокрутки пользователя. По мере загрузки данных эти заполнители заменяются вашим шаблоном элемента. Вы можете отключить функцию, задав ListViewBase.ShowsScrollingPlaceholders значение false, но если это сделать, рекомендуется использовать атрибут x:Phase для постепенной отрисовки элементов в шаблоне элемента. См. Постепенное обновление элементов ListView и GridView.

Ниже приведены дополнительные сведения о методах добавочной и случайной виртуализации данных.

Добавочная виртуализация данных

Добавочная виртуализация данных загружает данные последовательно. ListView, использующий добавочную виртуализацию данных, может использоваться для просмотра коллекции миллионов элементов, но изначально загружаются только 50 элементов. При перемещении или прокрутке пользователем загружаются следующие 50 элементов. По мере загрузки элементов большой палец полосы прокрутки уменьшается. Для этого типа виртуализации данных создается класс источника данных, реализующий эти интерфейсы.

Такой источник данных — это список в памяти, который может быть постоянно расширен. Элемент управления "Элементы" запрашивает элементы с помощью стандартного индексатора IList и свойств подсчета. Число должно представлять количество элементов локально, а не истинный размер набора данных.

Когда элемент управления элементами приближается к концу существующих данных, он вызывает ISupportIncrementalLoading.HasMoreItems. Если вы возвращаете true, он вызывает ISupportIncrementalLoading.LoadMoreItemsAsync, передавая рекомендованное количество элементов для загрузки. В зависимости от места загрузки данных из (локального диска, сети или облака) можно загрузить другое количество элементов, чем рекомендуется. Например, если служба поддерживает пакеты из 50 элементов, но элемент управления элементами запрашивает только 10, можно загрузить 50. Загрузите данные из бэкэнда, добавьте их в список и создайте уведомление об изменении с помощью INotifyCollectionChanged или IObservableVector<T>, чтобы элемент управления элементами знал о новых элементах. Также возвращает количество реально загруженных элементов. Если вы загружаете меньше элементов, чем рекомендуется, или элемент управления элементами был перемещен или прокручен еще дальше в промежуточном режиме, то источник данных будет вызван еще раз для дополнительных элементов и цикл продолжается. ISupportIncrementalLoading остается доступным в пакете SDK для приложений Windows, поэтому вы можете использовать тот же шаблон добавочной загрузки в приложении WinUI.

Виртуализация данных случайного доступа

Виртуализация данных случайного доступа позволяет загружать данные из произвольной точки в наборе данных. ListView, использующий виртуализацию данных случайного доступа для просмотра коллекции миллионов элементов, может загружать элементы 100 000–100 050. Если пользователь переходит к началу списка, элемент управления загружает элементы 1–50. Во всех случаях большой палец полосы прокрутки указывает, что ListView содержит миллион элементов. Позиция ползунка полосы прокрутки относительно того, где находятся видимые элементы во всем наборе данных коллекции. Этот тип виртуализации данных может значительно сократить требования к памяти и время загрузки для коллекции. Чтобы включить его, необходимо написать класс источника данных, который извлекает данные по запросу, управляет локальным кэшем и реализует эти интерфейсы.

IItemsRangeInfo предоставляет сведения о том, какие элементы элемента управления активно используются. Элемент управления элементами вызывает этот метод всякий раз, когда его представление изменяется, и включает в себя эти два набора диапазонов.

  • Набор элементов, находящихся в области видимости.
  • Набор элементов, не виртуализированных элементом управления, которые могут находиться вне поля видимости.
    • Буфер элементов вокруг окна просмотра, поддерживаемый для обеспечения плавного сенсорного сдвига.
    • Элемент с фокусом.
    • Первый элемент.

Реализуя IItemsRangeInfo, источник данных знает, какие элементы необходимо получить и кэшировать, а также когда следует обрезать данные из кэша, который больше не нужен. IItemsRangeInfo использует объекты ItemIndexRange для описания набора элементов на основе их индекса в коллекции. Это позволяет избежать указателей элементов, которые могут быть неверными или стабильными. IItemsRangeInfo предназначен для использования только одним экземпляром элемента управления элементами, так как он использует сведения о состоянии для этого элемента управления. Если для нескольких элементов управления требуется доступ к одному и тому же данным, для каждого из них требуется отдельный экземпляр источника данных. Они могут совместно использовать общий кэш, но логика очистки из кэша будет более сложной. IItemsRangeInfo остается доступным в пакете SDK для приложений Windows, поэтому те же методы кэширования случайного доступа применяются к элементам управления WinUI.

Вот базовая стратегия для вашего источника данных виртуализации данных с произвольным доступом.

  • При запросе элемента
    • Если он доступен в памяти, тогда верните его.
    • Если у вас его нет, верните null или элемент-заполнитель.
    • Используйте запрос на элемент (или сведения о диапазоне из IItemsRangeInfo), чтобы определить, какие элементы необходимы, и асинхронно получить данные для элементов из серверной части системы. После получения данных создайте уведомление об изменении с помощью INotifyCollectionChanged или IObservableVector<T> , чтобы элемент управления элементами знал о новом элементе.
  • (При необходимости) по мере изменения окна просмотра элемента управления определите, какие элементы необходимы из вашего источника данных через реализацию IItemsRangeInfo.

Помимо этого, ваша программа сама определяет стратегию, когда загружать элементы данных, сколько нужно загрузить и какие элементы хранить в памяти. Некоторые общие рекомендации, которые следует учитывать:

  • Выполнение асинхронных запросов к данным; Не блокируйте поток пользовательского интерфейса.
  • Найдите оптимальный размер партий, посредством которых вы запрашиваете элементы. Предпочитайте содержательное краткому и многословному. Не такие маленькие, чтобы вы делали слишком много небольших запросов; не такие большие, чтобы они занимали слишком много времени на извлечение.
  • Подумайте, сколько запросов вы хотите иметь в ожидании одновременно. Выполнение задач по одной проще, но это может быть слишком медленно, если время обработки велико.
  • Можно ли отменить запросы на данные?
  • Если используется размещенная служба, есть ли затраты на транзакцию?
  • Какие уведомления предоставляются службой при изменении результатов запроса? Знаете ли вы, вставляется ли элемент по индексу 33? Если ваша служба поддерживает запросы на основе ключа с смещением, это может оказаться более эффективным, чем использование только индекса.
  • Насколько интеллектуальной должна быть предварительная загрузка элементов? Вы собираетесь отслеживать направление и скорость прокрутки, чтобы предсказать, какие элементы необходимы?
  • Насколько агрессивно вы хотите быть в удалении кэша? Это компромисс памяти и опыта.