Flutter:提交单个字段时触发验证及控制器销毁问题
Flutter内联编辑功能的两个问题解决方案
问题1:TextEditingController的销毁处理
当前实现中每次调用buildFormField都会创建新的TextEditingController,但没有时机销毁,会引发内存泄漏。解决方式是将字段封装为StatefulWidget,在组件生命周期的dispose方法中销毁控制器。
修改后的组件实现
class InlineEditableField extends StatefulWidget { final String fieldName; final String fieldValue; final Function(String) onSubmitted; final String? Function(String?) validator; final TextInputType keyboardType; final bool isEditing; final VoidCallback onTap; const InlineEditableField({ super.key, required this.fieldName, required this.fieldValue, required this.onSubmitted, required this.validator, required this.keyboardType, required this.isEditing, required this.onTap, }); @override State<InlineEditableField> createState() => _InlineEditableFieldState(); } class _InlineEditableFieldState extends State<InlineEditableField> { late TextEditingController _controller; @override void initState() { super.initState(); _controller = TextEditingController( text: widget.fieldValue.replaceAll('\\$', '').replaceAll(',', ''), ); } @override void didUpdateWidget(covariant InlineEditableField oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.fieldValue != widget.fieldValue) { _controller.text = widget.fieldValue.replaceAll('\\$', '').replaceAll(',', ''); } } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return GestureDetector( onTap: widget.onTap, child: widget.isEditing ? TextFormField( controller: _controller, autofocus: true, onFieldSubmitted: widget.onSubmitted, keyboardType: widget.keyboardType, decoration: InputDecoration(labelText: widget.fieldName), validator: widget.validator, autovalidateMode: AutovalidateMode.onUserInteraction, ) : Padding( padding: const EdgeInsets.only(bottom: 6.0), child: Container( alignment: Alignment.centerLeft, child: RichText( text: TextSpan( children: [ TextSpan( text: '${widget.fieldName}: ', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), TextSpan( text: widget.fieldValue, style: const TextStyle( fontSize: 16, decoration: TextDecoration.underline, decorationStyle: TextDecorationStyle.dashed, ), ), ], ), ), ), ), ); } }
替换原调用
将原来的buildFormField调用替换为InlineEditableField:
InlineEditableField( fieldName: 'Purchase Price', keyboardType: TextInputType.number, fieldValue: Formatters.moneyFmt(widget.property.purchasePrice), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter a value'; } final parsedVal = double.tryParse(value); if (parsedVal == null || parsedVal <= 0) { return 'Please enter a valid positive number'; } return null; }, onSubmitted: (value) { // 后续验证逻辑见问题2解决方案 }, isEditing: selectedField == 'purchasePrice', onTap: () { setState(() { selectedField = 'purchasePrice'; }); }, )
问题2:Validator未生效,无法阻止非法提交
当前onSubmitted直接执行提交逻辑,未经过Form的验证流程。需要在提交前调用Form的validate()方法,仅当验证通过时才执行提交并退出编辑模式。
修改onSubmitted逻辑
onSubmitted: (value) { // 先触发表单验证 if (_formKey.currentState?.validate() ?? false) { final newProp = widget.property.copyWith( purchasePrice: double.tryParse(value) ?? 0.0); context.read<EditPropertyPageCubit>().update(newProp, widget.loans); setState(() { selectedField = null; }); } // 验证不通过则保留编辑状态 },
注意事项
确保在State类中已正确定义Form的全局Key:
final _formKey = GlobalKey<FormState>();
内容的提问来源于stack exchange,提问作者nktokyo
相关产品推荐
相关产品推荐

