Flutter问题:ViewModel频繁重建致TextEditingControllers重置
问题原因分析
你当前的问题核心在于 didChangeDependencies 的调用时机:这个方法会在组件依赖(比如Provider、屏幕尺寸变化、键盘弹出/收起触发的布局变更)发生变化时多次执行,每次调用 viewModel.setPost(widget.post) 都会重置ViewModel中的TextEditingControllers,导致输入内容丢失。
解决方法
1. 仅在组件初始化时设置一次Post
利用 initState 方法(组件生命周期中仅执行一次)来初始化ViewModel的Post数据,注意获取Provider时要加 listen: false(避免不必要的状态监听):
@override void initState() { super.initState(); // listen: false 表示不监听ViewModel的状态变化,仅获取实例 final viewModel = Provider.of<PostsViewModel>(context, listen: false); viewModel.setPost(widget.post); }
2. 处理Post更新场景(若父组件可能动态修改传入的Post)
如果父组件会在组件生命周期中更新传入的Post,需要在 didUpdateWidget 中对比新旧Post,仅当内容变化时才更新ViewModel:
@override void didUpdateWidget(covariant CreatePostWidget oldWidget) { super.didUpdateWidget(oldWidget); // 仅当新旧Post不同时才执行更新 if (oldWidget.post != widget.post) { final viewModel = Provider.of<PostsViewModel>(context, listen: false); viewModel.setPost(widget.post); } }
3. 在ViewModel层增加防护逻辑
优化 setPost 方法,确保只有当传入的Post与当前Post不同时,才重置TextEditingControllers:
class PostsViewModel extends ChangeNotifier { Post? _currentPost; final TextEditingController titleController = TextEditingController(); final TextEditingController contentController = TextEditingController(); void setPost(Post? newPost) { // 跳过相同Post的重复设置 if (_currentPost == newPost) return; _currentPost = newPost; // 初始化控制器内容 titleController.text = newPost?.title ?? ''; contentController.text = newPost?.content ?? ''; } // 务必释放控制器,避免内存泄漏 @override void dispose() { titleController.dispose(); contentController.dispose(); super.dispose(); } }
额外注意事项
- 获取ViewModel实例时,若不需要监听状态变化,必须加
listen: false,否则会触发组件不必要的重建; - 确保ViewModel的
dispose方法正确释放TextEditingControllers,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Salvatore La Fiura
相关产品推荐
相关产品推荐

