You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 在State类中新增控制器:
final _titleController = TextEditingController();
final _priceController = TextEditingController();
final _descriptionController = TextEditingController();
  1. 在dispose中销毁新增的控制器:
@override
void dispose() {
  _titleController.dispose();
  _priceController.dispose();
  _descriptionController.dispose();
  // 其他销毁操作...
}
  1. 给每个TextFormField绑定对应的控制器,移除onSaved:
// Title字段
TextFormField(
  controller: _titleController,
  // 其他属性保持不变
),

// Price字段
TextFormField(
  controller: _priceController,
  // 其他属性保持不变
),

// Description字段
TextFormField(
  controller: _descriptionController,
  // 其他属性保持不变
),
  1. 修改_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 11:18:13