Код-ревью Middle Производительность обновлено

Код-ревью: экран каталога

Вопрос

Экран каталога с поиском. Найдите проблемы производительности.

class _CatalogState extends State<Catalog> {
  String query = '';

  @override
  Widget build(BuildContext context) {
    final filtered = widget.products
        .where((p) => p.title.toLowerCase().contains(query.toLowerCase()))
        .toList()
      ..sort((a, b) => a.title.compareTo(b.title));
    return Column(children: [
      TextField(onChanged: (v) => setState(() => query = v)),
      Expanded(
        child: ListView(
          children: [for (final p in filtered) ProductTile(p)],
        ),
      ),
      Opacity(opacity: 0.9, child: Footer(stats: computeStats(widget.products))),
    ]);
  }
}

Коротко

Главная идея: build должен быть дешёвым. Вычисления делаются при изменении данных, а не при каждой отрисовке; длинные списки ленивые; setState охватывает минимальное поддерево; дорогие эффекты отрисовки заменяются простыми.

Что должен найти ревьюер

  1. Производительностьстрока 6
    Фильтрация и сортировка всего каталога в build на каждый символ ввода. Считать при изменении запроса (с debounce), для больших данных в изоляте.
  2. Производительностьстрока 9
    Сортировка всего списка каждый раз: каталог можно отсортировать один раз заранее, фильтрация сохраняет порядок.
  3. Производительностьстрока 11
    setState на весь экран при каждом символе перестраивает и Footer. Вынести поле и список в отдельный виджет или подписку.
  4. Производительностьстрока 13
    ListView(children:) строит все элементы. Нужен ListView.builder.
  5. Стильстрока 14
    У ProductTile нет ключа и const: при фильтрации элементы сопоставляются по позиции.
  6. Производительностьстрока 17
    computeStats по всему каталогу на каждом перестроении и Opacity над футером. Посчитать один раз, а прозрачность задать цветом.

Разбор

Главная идея: build должен быть дешёвым. Вычисления делаются при изменении данных, а не при каждой отрисовке; длинные списки ленивые; setState охватывает минимальное поддерево; дорогие эффекты отрисовки заменяются простыми.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.