如何取消嵌套Timer中的子Timer?
问题原因
你遇到的核心问题是:外层Timer在1秒时就已经执行了回调函数,创建了内部的子Timer。当1.5秒执行timer.cancel()时,外层Timer的任务已经完成,取消操作对已经创建的子Timer完全无效,所以子Timer仍会在1秒后(总时间2秒时)执行输出。
解决方案
针对复杂动画的时序管理需求,推荐以下几种可行方案:
方案1:用取消标记控制子Timer执行
通过一个布尔变量标记是否需要取消后续操作,创建子Timer前先检查标记状态:
import 'dart:async'; void main() async{ bool shouldCancel = false; final timer = Timer(const Duration(seconds: 1), () { print('Timer 1'); if (!shouldCancel) { Timer(const Duration(seconds:1),(){ print('Timer 2'); }); } }); Timer(Duration(milliseconds: 1500),(){ shouldCancel = true; timer.cancel(); print('timer cancelled'); }); }
执行结果符合预期:
Timer 1 timer cancelled
方案2:维护Timer集合统一管理
如果动画中有多个嵌套Timer,建议维护一个List<Timer>存储所有创建的Timer,取消时遍历集合逐个取消:
import 'dart:async'; void main() async{ final List<Timer> timers = []; final timer1 = Timer(const Duration(seconds: 1), () { print('Timer 1'); final timer2 = Timer(const Duration(seconds:1),(){ print('Timer 2'); }); timers.add(timer2); }); timers.add(timer1); Timer(Duration(milliseconds: 1500),(){ for (var t in timers) { t.cancel(); } timers.clear(); print('timer cancelled'); }); }
这种方式能确保所有相关Timer都被取消,适合复杂的多时序动画场景。
方案3:使用Stream或动画控制器(推荐)
对于Flutter动画场景,更推荐用Flutter自带的AnimationController或者基于Stream的时序管理,它们天生支持取消和生命周期管理,比手动嵌套Timer更可靠:
import 'dart:async'; void main() async{ final controller = StreamController<int>(); // 发送时序事件 Future.delayed(const Duration(seconds: 1), () => controller.add(1)); Future.delayed(const Duration(seconds: 2), () => controller.add(2)); final subscription = controller.stream.listen((event) { if (event == 1) print('Timer 1'); if (event == 2) print('Timer 2'); }); // 取消订阅 Timer(Duration(milliseconds: 1500),(){ subscription.cancel(); controller.close(); print('timer cancelled'); }); }
这种方式更贴合Flutter动画的设计模式,能更好处理用户交互导致的动画中断场景。
内容的提问来源于stack exchange,提问作者Calvin Andhika
相关产品推荐
相关产品推荐

