Как справиться с производительностью сортировки ListView?

У меня есть ListView, который отображает список сеансов чата (аналогично Whatsapp/Facebook Messenger) со следующими rowHasChanged:

rowHasChanged: (r1, r2) => r1.id !== r2.id

Я заметил, что элементы, которые не обновляются, перерисовываются, даже если я использую shouldComponentUpdate.

После некоторых следов я обнаружил, что, поскольку я сортирую элементы по-разному перед клонированием источника данных (новое сообщение заставляет элементы переходить в начало списка), rowHasChanged сравнивает разные строки. Есть смысл это сделать.

Но разве нет решения для эффективной сортировки? В WPF у нас был CollectionViewSource, который получил что-то для сортировки в дополнение к своим данным из-за той же проблемы (также поддерживается фильтрация и другие).

Кто-нибудь знает способ избавиться от этих избыточных рендеров?


person Moti Azu    schedule 11.01.2017    source источник
comment
ListViewDataSource использует неизменяемые данные, поэтому я не думаю, что это возможно с использованием ListView. Однако, если у вас включен removeClippedSubviews, не похоже, что он должен отображать очень много строк. Вы пробовали это?   -  person Garrett McCullough    schedule 05.02.2017
comment
@GarrettMcCullough Проблема не в неизменяемых данных или отображении слишком большого количества строк. Дело в том, что когда одна строка меняет свою позицию, это приводит к тому, что все остальные строки меняют свою позицию в моих данных, что приводит к тому, что ListView считает ВСЕ строки измененными строками, потому что он сравнивает разные строки друг с другом.   -  person Moti Azu    schedule 05.02.2017
comment
Моти, мой комментарий должен был сказать, что, поскольку вы используете неизменяемый объект данных, помещение новой записи в начало очереди является изменением структуры данных и, следовательно, потребует повторной обработки каждой строки. -рендеринг, потому что структура данных теперь другая. Однако, если у вас включен removeClippedSubviews, не имеет большого значения, что вы повторно отображаете все строки, потому что вы будете повторно отображать только видимые строки (плюс несколько дополнительных с каждой стороны), поэтому он должен не вызывает проблемы с производительностью. Вы также можете взглянуть на некоторые альтернативы ListView.   -  person Garrett McCullough    schedule 03.04.2017
comment
@GarrettMcCullough Неизменяемый массив здесь не будет проблемой. По этой причине у нас есть rowHasChanged, чтобы знать, какие строки должны быть перерисованы. Вы правы, говоря, что я должен брать цену повторного рендеринга только для моих видимых строк, но все же, если у меня есть 2 видимых строки, которые меняют свои позиции в моих данных (с индекса 0 на 1 или что-то), они оба будут повторно визуализировался, хотя никогда не менялся. Просто сменил позицию.   -  person Moti Azu    schedule 03.04.2017


Ответы (1)


Вы используете dataSource, как это?

this.setState({
    dataSource: this.ds.cloneWithRows(rowData)
});

Попробуйте использовать так:

this.setState(state => ({
    dataSource: this.state.dataSource.cloneWithRows(rowData)
}))

В первом случае вы устанавливаете новое значение для dataSource, поэтому он не будет использовать rowHasChanged и воспринимает его как новый источник данных.

person njafei    schedule 15.03.2017
comment
Нет, я постоянно использовал свой источник данных из штата. Проблема не в rowHasChanged, а в том, что вы не можете сортировать ListView, не вызывая, вероятно, ненужных повторных рендеров, потому что сравнение строк основано исключительно на индексе. - person Moti Azu; 15.03.2017