Представь ситуацию: тебе нужно выполнить определенный код только после того, как интерфейс полностью будет отрисован. Как быть? Конечно же, использовать addPostFrameCallback! Давайте разберем его.
Немного теории и фактов
▫️addPostFrameCallback – это метод класса WidgetsBinding, который наследуется от SchedulerBinding во Flutter
▫️ Он позволяет зарегистрировать функцию обратного вызова, которая появится после завершения отрисовки текущего кадра, но до начала следующего
▫️ Обратный вызов выполняется один раз и не может быть отменен
▫️ В качестве параметра обратный вызов получает Duration с указанием времени его вызова
Когда это может быть полезно?
▪️Показ диалогового окна после полной визуализации дерева виджетов
▪️Прокрутка к нужной позиции после построения UI
▪️Программная прокрутка к определенной позиции после построения интерфейса
▪️Запуск анимаций, зависящих от уже построенного UI
Ты можешь подумать: «Я же могу использовать StatefulWidget и реализовать все в initState без всяких addPostFrameCallback! В чем же польза?»
На самом деле, добавлять такую логику в initState — не самая лучшая идея. Вот почему:
▫️ initState вызывается до первой отрисовки виджета. Если ты попытаешься получить context или размеры виджетов в initState, ты можешь словить ошибку или просто получить нулевые значения, потому что виджеты еще не отрисованы и не имеют реальных размеров и позиций
▫️Если ты вызовешь setState() в initState, когда build() еще не закончился, ты получишь ошибку, похожую на > setState() or markNeedsBuild() called during build
▫️addPostFrameCallback, в отличие от этого, гарантирует, что все уже отрисовано и можно спокойно работать с контекстом
И осталось самое главное — разобраться, как использовать. Представим, нам нужно показать уведомление после того, как экран будет полностью отрисован.
class _SomeScreenState extends State<SomeScreen> {
@override
void initState() {
super.initState();
// Показываем snackbar после полной отрисовки интерфейса
WidgetsBinding.instance.addPostFrameCallback((_) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Some text')),
);
});
}
// build methodНа заметку:
✔️ Не используй addPostFrameCallback для тяжелых операций — они могут замедлить отрисовку следующего кадра
✔️ Если тебе нужно выполнять действия на каждом кадре, то addPostFrameCallback не подойдет
✔️ А если просто нужно отложить выполнение кода без привязки к UI — можно использовать Future.delayed или Future.microtask.
На этом все! А сейчас предлагаю выполнить addPostFrameCallback по версии Telegram и поставить ❤️
