Добавить объявление

Оптимизация работы анимаций во Flutter

Во Flutter анимации - это красиво, но если ими не управлять, они могут съедать ресурсы даже тогда, когда их никто не видит. Сегодня разберем два инструмента, которые помогут анимациям не тормозить интерфейс и не работать впустую.

AnimatedBuilder - перерисовываем только то, что нужно:


По умолчанию при каждом кадре анимации перестраивается весь виджет, который содержит AnimationController. Если внутри есть тяжелые элементы, это бьет по производительности.

AnimatedBuilder решает эту проблему. Он разделяет анимируемую часть и статический контент. Статический контент передается через параметр child и не пересоздается при каждом кадре. Перерисовывается только то, что реально меняется.

class ScaleButton extends StatefulWidget {
@override
_ScaleButtonState createState() => _ScaleButtonState();
}

class _ScaleButtonState extends State<ScaleButton> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;

@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 200),
vsync: this,
);
_animation = Tween<double>(begin: 1.0, end: 1.5).animate(_controller);
}

void _onTapDown(TapDownDetails details) {
_controller.forward();
}

void _onTapUp(TapUpDetails details) {
_controller.reverse();
}

@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: _onTapDown,
onTapUp: _onTapUp,
child: AnimatedBuilder(
animation: _animation,
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
),
child: const Center(
child: Text(
'Tap me',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
),
builder: (context, child) {
return Transform.scale(
scale: _animation.value,
child: child,
);
},
),
);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}
}

В этом примере статичная кнопка (синий квадрат с текстом) не пересоздается при каждом кадре - пересоздается только анимированное масштабирование вокруг нее.

TickerMode - останавливаем анимацию, когда ее не видно:


Если пользователь свернул приложение или переключился на другой экран, а анимация продолжает работать, это пустая трата ресурсов процессора и батареи.

TickerMode позволяет отключать все анимации в определенной части дерева виджетов. Достаточно обернуть нужный участок и передать enabled: false. Все AnimationController, связанные с TickerProviderStateMixin, автоматически приостановятся.

class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
bool _areAnimationsEnabled = true;

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
_areAnimationsEnabled = state != AppLifecycleState.paused;
});
}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Анимации')),
body: TickerMode(
enabled: _areAnimationsEnabled,
child: Center(
child: MyAnimatedWidget(),
),
),
);
}
}


Когда приложение уходит в фон, _areAnimationsEnabled становится false, и все анимации внутри TickerMode автоматически приостанавливаются. При возвращении в приложение анимации возобновляются сами.

Вывод:


AnimatedBuilder помогает не перерисовывать статику при каждом кадре, а TickerMode - не тратить ресурсы на анимацию, которую никто не видит. Вместе они делают приложение плавнее и экономичнее. Если вы используете анимации в своих проектах, эти два виджета должны быть в вашем арсенале.
05.06.2026 60 543