Pull to refresh

Comments 5

Частые вызовы setState (например, каждые 16–100 мс) перегружают UI поток ... Для анимаций есть специализированные инструменты: AnimationController, AnimatedBuilder, TweenAnimationBuilder.

Очень спорное утреверждение. setState не делает ничего, только маркирует виджет как грязный. Можно его вызывать хоть каждую микросекунду. В любом случае обновление будет только одно на следующем кадре. И все Animated сами по себе те же самые StatefulWidget и каждый тик дергают тот же самый setState. Только они жирные и цель их не оптимизация а простота использования.

setState не делает ничего, только маркирует виджет как грязный

Не верно.

setState по любому заставит перестроить нижележащее дерево виджетов. А если у вас приличное такое дерево виджетов, и у этих виджетов нет однозначных ключей и flutter не сможет однозначно сопоставить это дерево с деревом элементов (Element), то это уже потянет за собой и реальную перерисовку через дерево объектов рендеринга.

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

При этом не забывайте, что на подготовку всего дерева виджетов и на сравнение с деревом элементов у Flutter по хорошему есть только ~ 17ms в рамках одного кадра.
А при этом, возможно, ещё и какой-то полезный код приложения нужно успеть выполнить.

Например, я минимум две недели оптимизировал работу по показу каталога через animated_tree_view, потому что нужно было реагировать на любые изменения этого каталога из вне, а так же и непосредственное его редактирование в виджете. Пришлось придумывать разные ChangeNotifier-ы и грамотно расставлять Selector-ы для перехвата событий провайдера, чтобы снизить перестройку дерева даже в сложных моментах ниже 17ms для среднего железа клиента.

Не верно. setState по любому заставит перестроить нижележащее дерево виджетов

Зачем верить или нет. Нужно знать. Идем в исходники flutter и смотрим определение setState (отбросим assert, так как их все равно нет в рабочем приложении):
void setState(VoidCallback fn) {
final Object? result = fn() as dynamic;
_element!.markNeedsBuild();
}

Ну можем еще markNeedsBuild() проверить:
void markNeedsBuild() {
if (dirty) {
return;
}
_dirty = true;
owner!.scheduleBuildFor(this);
}

Ничего setState не перестраивает, только меняет булев флаг dirty.

Так что сколько его не жмакай хоть каждые 1 наносекунду перестройка будет не чаше чем раз на кадр.
И в статье речь не про сам setState а что лучше использовать виджеты анимации.
Но внезапно все анимационные виджеты наследуются от AnimatedWidget, который сам по себе StatefulWidget. И все анимации жмакают этот самый setState сразу после текущего кадра. Т.е. кадр отработался, они тут же считают значения на следующий кадр и банально дергают setState.

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

А вот неправда, если вы только сами себе проблем не сделали.
Листы по умолчанию заворачивают своих детей в RepaintBoundary. А это блокирует перерисовку вложенных виджетов. Поэтому при скролле дети не пересоздаются, хотя казалось бы дерево меняется.
Только если вы следуете "лучшим практикам иммутабельности" - самой идиотской идиоме, и на каждое движение пересоздаете весь список нижележащих данных.
Тогда да, убогая иммутабельность неизлечима :)

Ну значит я вашу мысль не верно дочитал
Правильно, setState через scheduleBuildFor ... как раз и приведет к перестройке всего дерева. на следующем кадре.
Но это не значит, что им всегда нужно безконтрольно пользоваться. Он так или иначе приведет к пересозданию всего нижележащего дерева виджетов - а это не всегда быстро с учётом сверки больших списков с нижележащими в библиотеке элементами, как бы не уверяли разработчики flutter и фаза UI в профайлере далеко не всегда укладыватся в 17 мс.

Только если вы следуете "лучшим практикам иммутабельности" - самой идиотской идиоме, и на каждое движение пересоздаете весь список нижележащих данных.Тогда да, убогая иммутабельность неизлечима :)

Как раз я забил на иммутабельность после первой же попытки ещё в первых тестах.
И перешёл на свой подход с версионностью данных.
НО в случае с деревом следить за каждым листом как оказалось во многих случаях не слишком удобно, особенно при drag & drop частей того же дерева и походу внутренних багах таких компонентов как, например, animated_tree_view, перебилживать всё дерево виджетов целиком всё равно временами приходится.

ПЫ СЫ flutter используется нами как раз не для мобильной, а для WEB и десктоп разработки. И походу с высоконагруженными интерфейсами он справляется иногда с трудом, судя по профайлеру. Иногда приходитмся бороться за каждый кадр, но junk-и всё равно присутствуют.

withOpacity создаёт новый цвет и не требует отдельного compositing layer, однако ⁠FadeTransition предпочтителен именно для анимированной прозрачности

Sign up to leave a comment.

Articles