Firestore Timer.periodic定时写入异常,如何实现15秒精准写入?
问题分析与解决方案
你的问题核心是在build方法中调用startTimer(),而build会因多种原因(如setState触发、屏幕旋转、父组件重建)频繁执行,每次执行都会创建一个新的定时任务。多个定时器同时运行就会导致数据被频繁写入,且旧定时器未被销毁会引发内存泄漏。
正确实现方式
1. 选择合适的生命周期管理定时器
将定时器的创建放在initState方法中(仅在组件初始化时执行一次),而非build方法。同时在dispose方法中销毁定时器,彻底避免内存泄漏。
2. 修改后的完整代码示例
class YourGameWidget extends StatefulWidget { const YourGameWidget({super.key}); @override State<YourGameWidget> createState() => _YourGameWidgetState(); } class _YourGameWidgetState extends State<YourGameWidget> { Timer? _timer; // 假设以下变量已提前定义或初始化 final CollectionReference games = FirebaseFirestore.instance.collection('games'); String documentNumber = 'target-doc-id'; dynamic player; @override void initState() { super.initState(); startTimer(); } void startTimer() { // 先销毁已有定时器,防止重复创建 _timer?.cancel(); const interval = Duration(seconds: 15); _timer = Timer.periodic( interval, (Timer timer) async { await games.doc(documentNumber).update({ 'players': FieldValue.arrayUnion([player.toString()]), }); }, ); } @override void dispose() { _timer?.cancel(); // 组件销毁时清理定时器 super.dispose(); } @override Widget build(BuildContext context) { // 这里只写UI相关代码,不再调用startTimer() return const Scaffold( body: Center(child: Text('Timer Running')), ); } }
3. 特殊场景优化
如果Firestore写入操作耗时可能超过15秒,建议改用Future.delay循环调用的方式,确保上一次写入完成后再等待15秒执行下一次,避免异步操作重叠:
void startTimer() async { _timer?.cancel(); while (mounted) { await Future.delayed(const Duration(seconds: 15)); await games.doc(documentNumber).update({ 'players': FieldValue.arrayUnion([player.toString()]), }); } }
注:mounted判断用于确保组件未被销毁时才继续执行循环。
内容的提问来源于stack exchange,提问作者A.Bokizh
相关产品推荐
相关产品推荐

