Flutter使用Provider时ViewModel旧数据重复填充,应如何清理?
问题根本原因
你当前的ViewModel是全局注册在应用顶层MultiProvider中,属于全局单例实例,生命周期和整个App一致,页面关闭不会销毁实例,所以旧数据会一直留存。
最优解决方案:缩小Provider作用域(推荐)
不要把仅业务页面使用的ViewModel注册到全局,直接将Provider绑定到对应页面的路由层级,页面销毁时Provider会自动释放ViewModel实例,下次进入页面自动创建全新实例,无需手动写reset逻辑:
// 首页跳转逻辑修改 onPressed(){ Navigator.push( context, MaterialPageRoute( builder: (context) => ChangeNotifierProvider( create: (context) => ViewModel1(), child: FirstPage(), ) ) ); }
同时删除原来全局MultiProvider里的ChangeNotifierProvider.value(value: ViewModel1())配置即可。这种方式完全避免了旧数据残留问题,是最符合Provider设计规范的用法。
方案二:页面销毁时自动触发reset(适合ViewModel需要全局留存的场景)
如果你的ViewModel1确实需要在多个页面共享数据,必须全局注册,那不要在跳转前调用reset,而是在FirstPage的dispose生命周期中调用,避免跳转时的时序问题(你当前代码先push页面再reset,可能出现页面先加载旧数据再被清空的闪烁问题):
class _FirstPageState extends State<FirstPage> { @override void dispose() { // 页面关闭时自动重置 Provider.of<ViewModel1>(context, listen: false).reset(); super.dispose(); } @override Widget build(BuildContext context) { final ViewModel1 _viewModel1 = Provider.of<ViewModel1>(context, listen: true); return TextFormField( controller: _fNameController, onChanged: _viewModel1.setFname, ); } }
方案三:封装自动reset逻辑(多页面复用场景)
如果多个页面都需要用到reset逻辑,可以封装一个自动清理的mixin,减少重复代码:
mixin AutoResetViewModel<T extends ChangeNotifier> on State<StatefulWidget> { @override void dispose() { Provider.of<T>(context, listen: false).reset(); super.dispose(); } } // 页面使用 class _FirstPageState extends State<FirstPage> with AutoResetViewModel<ViewModel1> { // 无需再手动重写dispose }
内容的提问来源于stack exchange,提问作者LIJU DANIEL
相关产品推荐
相关产品推荐

