Flutter MVVM+Provider中ViewModel仅初始化一次,页面切换数据未清除的解决方法
解决Flutter Provider全局ViewModel页面切换后数据不重置的问题
问题根源
你在MultiProvider中全局注册的LoginViewModel和CreateAccountViewModel是单例实例,整个应用生命周期内只会创建一次。切换页面时不会触发ViewModel的重建,所以之前输入的数据会保留,构造函数也只会执行一次——lazy: false仅控制实例提前初始化,无法改变单例的本质。
解决方案
方案1:页面层级注册ViewModel(最优解)
取消全局注册,在登录/注册页面的路由中单独注册ViewModel,这样每次进入页面都会创建新的实例,自动重置数据。
示例代码:
// 登录页路由配置 MaterialPageRoute( builder: (context) => ChangeNotifierProvider( create: (_) => LoginViewModel(), child: const LoginPage(), ), ), // 注册页路由配置 MaterialPageRoute( builder: (context) => ChangeNotifierProvider( create: (_) => CreateAccountViewModel(), child: const CreateAccountPage(), ), ),
此方案符合MVVM设计原则,登录/注册页面的ViewModel无需全局共享,页面层级绑定能保证ViewModel生命周期与页面一致,进入页面时自动初始化新实例,清空之前的输入数据。
方案2:给ViewModel添加重置方法(全局注册场景)
如果必须保留全局注册,可在ViewModel中添加重置逻辑,然后在页面加载时调用。由于使用StatelessWidget,需借助WidgetsBinding实现初始化回调:
- 在ViewModel中添加重置方法:
class LoginViewModel extends ChangeNotifier { late TextEditingController emailController; late TextEditingController passwordController; LoginViewModel() { _initControllers(); print("LoginViewModel initialized"); } void _initControllers() { emailController = TextEditingController(); passwordController = TextEditingController(); } // 重置所有页面数据 void resetData() { emailController.clear(); passwordController.clear(); // 如有其他状态(如错误提示、复选框状态),在此一并重置 notifyListeners(); } }
- 在StatelessWidget的build方法中触发重置:
class LoginPage extends StatelessWidget { const LoginPage({super.key}); @override Widget build(BuildContext context) { // 页面构建完成后执行重置 WidgetsBinding.instance.addPostFrameCallback((_) { Provider.of<LoginViewModel>(context, listen: false).resetData(); }); return Scaffold( // 页面UI内容 ); } }
注意:listen: false表示仅调用方法,不监听状态变化。
内容的提问来源于stack exchange,提问作者Adhi
相关产品推荐
相关产品推荐

