Flutter AnimatedBuilder 继承自 AnimatedWidget,它的作用是生成一个有动画功能的 StatefulWidget widget 作为复杂 widget 的一部分。
源码分析
typedef TransitionBuilder = Widget Function(BuildContext context, Widget? child);
class AnimatedBuilder extends AnimatedWidget {
const AnimatedBuilder({
super.key,
required Listenable animation,
required this.builder,
this.child,
}) : assert(animation != null),
assert(builder != null),
super(listenable: animation);
final TransitionBuilder builder;
final Widget? child;
@override
Widget build(BuildContext context) {
return builder(context, child);
}
}
源码非常简单。主要就一句代码 return builder(context, child); builder 通过参数传进来,让我们可以通过 builder 自定义 widget。
通过继承 AnimatedWidget 的方式自定义动画,我们不得不先自定义一个类出来。用 AnimatedBuilder 会更简洁。
使用 AnimatedBuilder
使用 AnimatedBuilder 很简单的,只需要给他一个 listenable 对象,一个 builder 函数。
还是拿上次 AnimatedWidget 的例子,不断放大的正方形,看看用 AnimatedBuilder 如何写。
class _MyAnimationState extends State<MyAnimation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1))
..repeat();
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
width: _controller.value * 100,
height: _controller.value * 100,
color: Colors.blue[200],
);
},
))));
}
}
和直接用 AnimatedWidget 的实现方式相比,代码确实简洁很多。AnimatedBuilder 让动画 widget 以内嵌的方式嵌入到其它 widget 当中,省去了自定类。
但是 AnimatedBuilder 也是有他的不足的,如果要多次复用动画 Widget ,还是用直接继承 AnimatedWidget 的方式比较好。
性能优化
每当做动画效果的时候,都要认真考虑性能的问题,因为动画的刷新频率太高了,稍有不慎就会造成卡顿。builder 的参数 child 就是为优化准备的。
AnimatedBuilder(
animation: _controller,
child: Container(
color: Colors.blue,
),
builder: (context, child) {
return SizedBox(
width: _controller.value * 100,
height: _controller.value * 100,
child: child);
},
)
我们可以把不参与动画的部分单拿出来。child 只会 build 一次。如果 child 放在builder 里面的话,每当 frame 刷新都会 build 一次。
还有一个办法是 用 const 关键字。这个前面在 AnimatedWidget 中已经举过例子了,不再赘述。