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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 15:05:09