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
相关产品推荐
相关产品推荐

