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

Flutter Timer管控异常:后台运行、dispose失效及页面返回问题

问题分析

用Navigator.push跳转页面时,原页面并不会被销毁,所以dispose方法不会执行,Timer自然不会被取消。你手动调用dispose()的做法是错误的,这会破坏Flutter的生命周期管理,无法真正解决问题。

解决方案

通过监听页面的路由可见状态来控制Timer的启停,具体实现如下:

1. 全局配置RouteObserver

在你的MaterialApp所在文件中,先定义全局的RouteObserver实例,并配置到MaterialApp中:

final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();

MaterialApp(
  navigatorObservers: [routeObserver],
  // ...其他页面配置
);

2. 修改原页面的State类

让State类混入RouteAware,实现路由监听方法来控制Timer的启停:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:provider_2_practice/controller/controller_file.dart';
import 'new_screen.dart';

// 和MaterialApp中配置的全局实例保持一致
final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();

class MyHomePageUI extends StatefulWidget {
  @override
  State<MyHomePageUI> createState() => _MyHomePageUIState();
}

class _MyHomePageUIState extends State<MyHomePageUI> with RouteAware {

  Timer? timer ;
  String abc ='df-1'; //default value: 'df-1'

  @override
  void initState() {
    super.initState();
    _startTimer();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 注册路由监听
    routeObserver.subscribe(this, ModalRoute.of(context)!);
  }

  @override
  void dispose() {
    // 取消路由监听和Timer
    routeObserver.unsubscribe(this);
    _stopTimer();
    super.dispose();
  }

  // 跳转到下一页时触发,停止Timer
  @override
  void didPushNext() {
    super.didPushNext();
    _stopTimer();
  }

  // 从下一页返回时触发,重启Timer
  @override
  void didPopNext() {
    super.didPopNext();
    _startTimer();
  }

  // 封装启动Timer的方法
  void _startTimer() {
    timer?.cancel(); // 先取消已有Timer,避免重复创建
    timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
      if(mounted){
        setState( () {
          abc = DateFormat('hh:mm:ss a').format(DateTime.now());
        } );
      }
      print(abc);
    });
  }

  // 封装停止Timer的方法
  void _stopTimer() {
    timer?.cancel();
    timer = null; // 置空避免内存泄漏
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.lightBlue[900],
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewScreen()));
        },
        child: const Icon(Icons.add,  color: Colors.white),
        backgroundColor: Colors.blue,
      ),
      body: Column(
        children: [
          const SizedBox(height:100,),
          Text(abc, style: const TextStyle(fontSize: 45, fontWeight: FontWeight.bold,color: Colors.white70),),
          const Text('current time', style: TextStyle(  fontWeight: FontWeight.bold,color: Colors.white),),
        ],
      ),
    );
  }
}

关键说明

  • 移除了手动调用dispose()的代码,让Flutter框架负责页面生命周期管理。
  • 通过RouteAware和RouteObserver精准监听页面路由切换:
    • didPushNext:当前页面被新页面覆盖(跳转至第二页)时,停止Timer。
    • didPopNext:从第二页返回当前页面时,重启Timer。
  • 封装_startTimer和_stopTimer方法,避免代码重复,同时防止Timer重复创建导致的异常。

内容的提问来源于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.13 18:35:41