在Flutter的showDialog中使用watch_it访问模型的视图重绘问题
解决watch_it在Flutter弹窗中无法同步模型更新的问题
核心原因
showDialog 创建的弹窗是独立于主Widget树的新上下文,默认情况下弹窗内的Widget不会自动订阅watch_it的模型变化,导致模型更新后弹窗无法重绘。
具体解决方法
方法1:在弹窗内使用 WatchItBuilder 包裹需要响应变化的Widget
直接在弹窗的Widget树中用WatchItBuilder监听目标模型,模型更新时会自动触发重绘:
showDialog( context: context, builder: (dialogContext) { return WatchItBuilder<YourModel>( builder: (context, model) { return AlertDialog( title: Text(model.someValue), actions: [ TextButton( onPressed: () => Navigator.pop(dialogContext), child: const Text('关闭'), ), ], ); }, ); }, );
替换YourModel为你的实际模型类,model.someValue为需要同步的属性即可。
方法2:在自定义弹窗Widget中手动订阅模型
如果弹窗是自定义StatefulWidget,可在生命周期中手动订阅和取消订阅:
class CustomDialog extends StatefulWidget { const CustomDialog({super.key}); @override State<CustomDialog> createState() => _CustomDialogState(); } class _CustomDialogState extends State<CustomDialog> { late YourModel _model; late VoidCallback _unsubscribe; @override void initState() { super.initState(); _model = getIt<YourModel>(); // 订阅模型变化,触发setState更新UI _unsubscribe = watchIt.watch<YourModel>((_) => setState(() {})); } @override void dispose() { _unsubscribe(); // 取消订阅,避免内存泄漏 super.dispose(); } @override Widget build(BuildContext context) { return AlertDialog( title: Text(_model.someValue), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('关闭'), ), ], ); } }
使用时直接在showDialog的builder中返回这个自定义Widget即可。
方法3:使用 watch 扩展函数监听单个属性
如果只需要监听模型的某个特定属性,可用watch扩展函数简化代码:
showDialog( context: context, builder: (dialogContext) { final someValue = dialogContext.watch<YourModel>((m) => m.someValue); return AlertDialog( title: Text(someValue), actions: [ TextButton( onPressed: () => Navigator.pop(dialogContext), child: const Text('关闭'), ), ], ); }, );
该方式会自动监听指定属性的变化,属性更新时弹窗会自动重绘。
注意事项
- 确保模型类已通过
getIt.registerSingleton或类似方法注册到watch_it的依赖注入容器中。 - 方法2需手动取消订阅,方法1和3会自动管理订阅生命周期,无需额外处理。
内容的提问来源于stack exchange,提问作者freebie
相关产品推荐
相关产品推荐

