Xamarin Forms SearchBar + ListView медленно обновляется - PullRequest
0 голосов
/ 02 мая 2018

Мне нужна помощь в ускорении процесса фильтрации длинного списка элементов списка и их просмотра в ListView.

Мое приложение имеет панель поиска, ListView и очень длинный список строк на выбор.

Когда пользователь вводит критерий поиска, ListView обновляется при каждом нажатии клавиши и отфильтровывает нерелевантные элементы.

Сама сортировка занимает несколько миллисекунд, но последующее обновление ListView новым событием filter занимает много времени (20 секунд легко, если в качестве критерия поиска был введен только один символ)

Я полагаю, что время затрачивается на большое количество ViewCells каждый раз, когда обновляется отфильтрованный список.

Кто-нибудь из вас знает, как ускорить процесс? Я подумал, что он может работать с очень ограниченным числом ViewCells (например, 10 или 20), а затем обновлять их и просто отображать выбор отфильтрованного списка. При прокрутке можно было бы повторно использовать верхнюю / нижнюю часть, обновить содержимое и поместить его обратно в нижнюю / верхнюю часть, но я не смог понять, как это сделать.

Может быть, это неправильный подход, и вы знаете лучший способ?

1 Ответ

0 голосов
/ 18 мая 2018

У меня просто была похожая проблема, что мой список, содержащий всего 20 элементов, работал бы очень медленно. Может быть, ваша проблема похожа. К сожалению, вы не опубликовали код. У меня было что-то вроде этого:

List l = originalItems.Where((i) => i.Name.Contains(filterText));
listView.ItemsSource = l;

И я не мог понять, почему это так медленно. Я нашел другой подход с большими накладными расходами, который по какой-то причине быстрее и отзывчивее и в целом удобнее для пользователя. Мой ListView всегда имеет ObservableCollection как ItemsSource. Когда я фильтрую, я вычисляю разницу с этим ObservableCollection (дополнительные элементы и удаленные элементы), а затем удаляю или добавляю соответственно. Это позволяет избежать замены свойства ItemsSource, которое кажется слишком грубым для ListView.

//property of the class
ObservableCollection<FlightListItem> listViewItems;
// ....
//somewhere at initialization
listView.ItemsSoure = listViewItems;
// ....
//in the filter method:
List l = originalItems.Where((i) => i.Name.Contains(filterText));
IEnumerable itemsToAdd = l.Except(listViewItems).ToList();
IEnumerable itemsToRemove = listViewItems.Except(l).ToList();
listView.BeginRefresh();
foreach (FlightListItem item in removes)
    listViewItems.Remove(item);
foreach (FlightListItem item in added)
    listViewItems.Add(item);
listView.EndRefresh();

Примечания:

  • удаление listView.BeginRefresh() и EndRefresh(), похоже, не повлияло на производительность, но, кажется, их здесь правильно называть.
  • Нам нужно позвонить ToList() на itemsToAdd и itemsToRemove, хотя нам нужно только IEnumerables! Это связано с тем, что Except является отложенной операцией, в противном случае она будет выполняться только во время цикла for. Однако во время цикла for один из параметров, за исключением изменений, приводит к IllegalArgumentException из-за изменения IEnumerable при переходе по нему.
  • Если кто-нибудь знает хорошую фильтруемую наблюдаемую коллекцию, которая, вероятно, будет более хорошим решением.
...