Flutter返回页面出现FocusNode已释放仍被使用错误及代码优化咨询
问题解决:FocusNode报错与onSaved代码简化
一、解决“A FocusNode was used after being disposed”错误
错误根源是你在dispose方法中先销毁了_imageurlfocusnode,之后才尝试移除它的监听器——此时FocusNode已经被释放,再对它执行操作就会触发报错。
修复方法:调整dispose中的执行顺序,先移除监听器,再销毁所有FocusNode和控制器:
@override void dispose() { // 先移除监听器 _imageurlfocusnode.removeListener(_updateimage); // 再销毁所有资源 _pricefocusnode.dispose(); _titlefocusnode.dispose(); _descriptionfocusnode.dispose(); _imageurlcontroller.dispose(); _imageurlfocusnode.dispose(); super.dispose(); }
二、简化TextFormField的onSaved代码
你的onSaved逻辑重复是因为每次都手动创建新的Product实例并复制所有未修改字段,这里提供两种优化方案:
方案1:给Product类添加copyWith方法
给Product类新增一个copyWith方法,用于快速复制对象并修改指定字段:
class Product { final String description; final String title; final String id; final double price; final String imageUrl; Product({ required this.description, required this.title, required this.id, required this.price, required this.imageUrl, }); // 添加copyWith方法 Product copyWith({ String? description, String? title, String? id, double? price, String? imageUrl, }) { return Product( description: description ?? this.description, title: title ?? this.title, id: id ?? this.id, price: price ?? this.price, imageUrl: imageUrl ?? this.imageUrl, ); } }
之后每个TextFormField的onSaved可以简化为一行代码:
// Title字段的onSaved onSaved: (value) { _tempproduct = _tempproduct.copyWith(title: value.toString()); }, // Price字段的onSaved onSaved: (value) { _tempproduct = _tempproduct.copyWith(price: double.parse(value.toString())); }, // Description字段的onSaved onSaved: (value) { _tempproduct = _tempproduct.copyWith(description: value.toString()); }, // ImageUrl字段的onSaved onSaved: (value) { _tempproduct = _tempproduct.copyWith(imageUrl: value.toString()); },
方案2:直接在_saverecord中一次性收集表单数据
如果不想修改Product类,可以给每个TextFormField绑定控制器,在保存时直接从控制器取值创建Product:
- 在State类中新增控制器:
final _titleController = TextEditingController(); final _priceController = TextEditingController(); final _descriptionController = TextEditingController();
- 在dispose中销毁新增的控制器:
@override void dispose() { _titleController.dispose(); _priceController.dispose(); _descriptionController.dispose(); // 其他销毁操作... }
- 给每个TextFormField绑定对应的控制器,移除onSaved:
// Title字段 TextFormField( controller: _titleController, // 其他属性保持不变 ), // Price字段 TextFormField( controller: _priceController, // 其他属性保持不变 ), // Description字段 TextFormField( controller: _descriptionController, // 其他属性保持不变 ),
- 修改_saverecord方法,直接从控制器取值创建Product:
void _saverecord() { final result = _form.currentState?.validate(); if (!result!) return; final newProduct = Product( title: _titleController.text, price: double.parse(_priceController.text), description: _descriptionController.text, imageUrl: _imageurlcontroller.text, id: '', ); Provider.of<ProductsProvider>(context, listen: false) .addproduct(newProduct); }
这种方式完全消除了重复的onSaved代码,逻辑更集中。
内容的提问来源于stack exchange,提问作者Irfan Ganatra
相关产品推荐
相关产品推荐

