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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:05:17