Flutter使用Navigation.push跳转时如何保存忘记密码页倒计时状态
问题原因
每次调用Navigator.push进入ForgotPassword页面时,都会创建一个全新的页面实例,从该页面pop返回登录页时,旧的忘记密码页面实例会被销毁,存储在页面State中的倒计时时长、发送状态、输入的邮箱内容都会被清空,因此再次进入时状态丢失。
可行解决方案
1. 状态提升/全局状态管理(最推荐)
将需要保留的状态(倒计时剩余时长、是否已发送重置邮件、邮箱输入内容)从ForgotPassword页面的State中抽离,放到两个页面的共同父节点,或通过Provider、GetX、Bloc等全局状态管理工具存储,每次进入忘记密码页时从全局状态读取数值初始化页面即可。
如果需要重启App仍保留状态,可搭配SharedPreferences做本地持久化存储。
2. 提前缓存页面实例保活
提前在登录页上层创建唯一的ForgotPassword实例,每次调用Navigator.push时复用这个已创建的实例,同时给_ForgotPasswordState混入AutomaticKeepAliveClientMixin,重写wantKeepAlive返回true,避免页面被系统回收销毁。
3. 调整路由跳转逻辑
如果你的操作路径是「忘记密码页→返回登录页」,可以不pop掉忘记密码页,改为将登录页以覆盖层/弹窗的形式推到路由栈上层,忘记密码页会一直保留在栈中不被销毁,返回时状态自然留存。
现有代码优化点
你当前的dispose方法中直接调用_timer!.cancel()存在空安全风险,万一_timer还未初始化就销毁页面会触发崩溃,修改为判空调用即可:
@override void dispose() { _timer?.cancel(); super.dispose(); }
状态提升简易示例(基于Provider)
首先创建独立的状态类:
import 'package:flutter/foundation.dart'; import 'dart:async'; class ForgotPwdGlobalState extends ChangeNotifier { bool hasSent = false; int countDown = 0; String inputEmail = ''; Timer? _timer; void startCountDown() { if (countDown > 0) return; countDown = 30; _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (countDown == 0) { timer.cancel(); } else { countDown--; } notifyListeners(); }); notifyListeners(); } @override void dispose() { _timer?.cancel(); super.dispose(); } }
在应用上层将状态注入,之后在ForgotPassword页面中直接读取该状态的数值渲染UI,状态不受页面销毁影响。
内容的提问来源于stack exchange,提问作者Anim

