Хотя ListView является двольно мощным элементом для отображения данных, он все таки имеет некоторые ограничения. При определении сложного содержимого, сложной структуры ячеек в ListView может ухудшиться скроллинг, поскольку при пролистывании системе нужно будет выполнить множество вычислений. Однако существуют приемы и способы, которые позволят повысить роизводительность и постараться нивелировать возможный отрицательный эффект при подобных действиях.
Элемент ListView в Xamarin Forms опирается на нативные реализации этого элемента на Android, iOS, UWP, и на каждой из этих платформ реализации ListView имеют встроенные возможности по кэшированию ранее использованных строк. То есть, как правило, в память загружаются только те ячейки ListView, которые в текущий момент видны на экране. Соответственно контент загружается только в эти ячейки. Это позволяет не создавать тысячи объектов, которые номинально имеются в списке, тем самым уменьшая потребление памяти.
В Xamarin.Forms существуют две стратегии кэширования, которые описываются перечислением ListViewCachingStrategy. Для каждой стратегии в этом перечислении определено соответствующее значение:
RetainElement
RecycleElement
По умолчанию к ListView в Xamarin.Forms применяется значение RetainElement. Оно означает, что ListView будет создавать ячейку для каждого элемена в списке.
В каких случаях данная стратегия может быть предпочтительной:
Когда каждая ячейка ListView имеет большое количество привязок (20-30 и более)
Когда шаблон ячейки часто меняется
Когда другая стратегия RecycleElement при тех же условиях показывает худшие результаты
RecycleElement позволяет повторно использовать одни и те же ячейки, вместо их создания каждый раз, когда они попадают в зону видимости. Эта стратегия может быть предпочтительной в следующих случаях:
Когда каждая ячейка ListView имеет небольшое количество привязок
Когда свойство BindingContext ячейки определяет все ее данные
Когда ячейки во многом аналогичны, а их шаблон остается неизменным
Для установки стратегии кэширования у ListView в XAML применяется атрибут CachingStrategy:
<ListView CachingStrategy="RecycleElement"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> ... </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
В коде C# аналогом является передача в конструктор значения ListViewCachingStrategy:
ListView listView = new ListView(ListViewCachingStrategy.RecycleElement);
Оптимальнее к свойству ItemsSource привязывать объект IList<T>
вместо
IEnumerable<T>
, так как коллекции IEnumerable<T>
не поддерживают произвольный доступ.
Где возможно, используйте встроенные типы ячеек - TextCell или ImageCell вместо ViewCell.
Используйте как можно меньше элементов.
Если необходимо вывести данные различных типов, используйте элемент TableView вместо ListView.
Ограничено используйте метод Cell.ForceUpdateSize
, так как он снижает производительность.
На Android избегайте установки видимости или цвета разделителя элементов в ListView, после инициализации ListView.
Избегайте изменения ячеек, которые основаны на BindingContext
Избегайте глубоковложенных иерархий элементов. Вместо подобных иерархий используйте AbsoluteLayout или Grid, чтобы уменьшить уровни вложенности элементов.
Избегайте установки любого значения структуры LayoutOptions
, кроме значения Fill
, так как на при этом значении на вычисления тратятся наименьшие ресурсы.
Избегайте размещения ListView внутри ScrollView, так как ListView имеет свой собственный скроллинг
Если необходимо построение комплексной сложной ячейки, то лучше для этой цели лучше создать новый элемент с помощью рендереров. Это поможет снизить отрицательный эффект от вычислений при скроллинге в списке.
AbsoluteLayout в ряде случаев может производить компоновку элементов вообще без вычислений, что делает данный элемент довольно производительным. Если по каким-то причинам AbsoluteLayout не может использоваться, стоит посмотреть в сторону RelativeLayout. При использовании RelativeLayout передавайте применяемым ограничениям (Constraints) прямые значения, вместо использования выражений.