You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:40:06