Flutter:动画控制器停止后调度器抛出异常问题排查
问题分析与修复
你的代码触发调度器异常的核心原因:在**动画状态回调(StatusListener)**里直接调用_animationController.stop(),此时调度器正处于处理当前回调的上下文,直接修改动画状态会打乱调度队列,引发异常。同时原代码的计数逻辑和停止后的状态处理也存在优化空间。
修复后的完整代码
class MyBlinkingIcon extends StatefulWidget { const MyBlinkingIcon({super.key}); @override MyBlinkingIconState createState() => MyBlinkingIconState(); } class MyBlinkingIconState extends State<MyBlinkingIcon> with SingleTickerProviderStateMixin { late AnimationController _animationController; int _blinkCount = 0; bool _blinkingDone = false; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(seconds: 1), ); _animationController.addStatusListener((status) { // 每次动画从透明回到完全可见,算作一次完整闪烁 if (status == AnimationStatus.completed) { _blinkCount++; if (_blinkCount == 3) { // 延迟到当前帧绘制完成后再修改动画状态,规避调度器异常 WidgetsBinding.instance.addPostFrameCallback((_) { setState(() => _blinkingDone = true); _animationController.stop(); // 强制设置动画值为1,确保图标停止后保持可见 _animationController.value = 1.0; }); } else { // 继续下一次闪烁循环 _animationController.reverse(); } } else if (status == AnimationStatus.dismissed) { // 从透明状态回到可见状态 _animationController.forward(); } }); // 启动第一次闪烁 _animationController.forward(); } @override Widget build(BuildContext context) { return _blinkingDone ? Assets.svgs.flame.svg() : FadeTransition( opacity: _animationController, child: Assets.svgs.flame.svg(), ); } @override void dispose() { _animationController.dispose(); super.dispose(); } }
核心修复说明
- 规避调度器异常:用
WidgetsBinding.instance.addPostFrameCallback延迟执行动画停止操作,让当前调度回调完成后再修改动画状态,避免上下文冲突。 - 准确控制闪烁次数:以
AnimationStatus.completed(动画回到完全可见状态)作为一次闪烁的结束标记,确保正好完成3次闪烁后停止。 - 停止后保持可见:主动将动画控制器的
value设为1.0,防止图标停在透明状态。 - 简化状态判断:用
_blinkingDone布尔值替代计数器判断,逻辑更清晰,减少不必要的状态更新。
内容的提问来源于stack exchange,提问作者Farhana Naaz Ansari
相关产品推荐
相关产品推荐

