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

Flutter中Timer调用cancel()后仍后台运行报不安全查找祖先错误

彻底停止Flutter后台Timer的解决方案

问题根源

  • 使用ConsumerWidget(无状态组件)管理Timer,但无状态组件没有**dispose生命周期方法**,无法在组件销毁时主动终止Timer。
  • build方法会被多次触发(如父组件重建、状态更新),每次调用runTimerClock都会重建Timer;组件退出后,未被正确取消的Timer仍会后台运行,且回调中持有的WidgetRef已关联失效组件,从而触发Looking up a deactivated widget's ancestor is unsafe错误。

修正后的代码

将组件改为ConsumerStatefulWidget,利用State类的生命周期管理Timer,确保组件销毁时彻底终止Timer:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';

// 将Provider移到组件外部,避免每次创建组件时重复定义
final myStateProviderTime2 = StateProvider((ref) => 'state time');

class TimerClockQuestion extends ConsumerStatefulWidget {
  const TimerClockQuestion({super.key});

  @override
  ConsumerState<TimerClockQuestion> createState() => _TimerClockQuestionState();
}

class _TimerClockQuestionState extends ConsumerState<TimerClockQuestion> {
  Timer? timerClock2;
  String currentTime = '12:00 AM';

  @override
  void initState() {
    super.initState();
    // 仅在组件初始化时创建Timer
    runTimerClock();
  }

  @override
  void dispose() {
    // 组件销毁时强制取消Timer,彻底终止后台任务
    timerClock2?.cancel();
    super.dispose();
  }

  void runTimerClock() {
    // 先取消旧Timer,避免重复执行
    timerClock2?.cancel();
    timerClock2 = Timer.periodic(const Duration(seconds: 1), (timer) {
      currentTime = DateFormat('hh:mm:ss a').format(DateTime.now());
      ref.read(myStateProviderTime2.notifier).state = currentTime;
      print(currentTime);
    });
  }

  @override
  Widget build(BuildContext context) {
    currentTime = ref.watch(myStateProviderTime2);

    return Scaffold(
      body: Center(
        child: Text(
          currentTime,
          style: const TextStyle(fontSize: 50, color: Colors.white38),
        ),
      ),
    );
  }
}

关键修改说明

  • 改用ConsumerStatefulWidget:通过State类的initState初始化Timer,dispose方法在组件销毁时执行Timer取消操作,确保Timer生命周期与组件绑定。
  • 避免build重复创建Timer:将Timer初始化移至initState,防止build多次触发导致的Timer重复创建问题。
  • 强制终止Timer:dispose中的timerClock2?.cancel()是组件销毁时的最后保障,彻底停止后台运行的Timer,避免无效的ref调用。

内容的提问来源于stack exchange,提问作者Saad Mansoor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:05:25