Flutter中TextFormField从JSON数组取值后无法修改内容求助
解决Flutter TextFormField编辑后关闭键盘恢复初始值的问题
问题场景
从JSON数组列表读取值并显示到TextFormField后,编辑输入框内容时,每次关闭键盘都会自动恢复为JSON中的初始值。
核心原因
这个问题的本质是TextFormField没有和状态变量做双向绑定,而是直接引用了JSON中的原始静态值。当键盘收起触发组件重建(比如布局重绘)时,TextFormField会重新读取JSON的初始值,覆盖用户编辑后的内容。
两种可行解决方案
方案1:使用TextEditingController(推荐)
通过控制器直接管理输入框的文本内容,初始化时将JSON值赋值给控制器,后续用户输入会自动同步到控制器,组件重建时也会读取控制器中的最新值。
class JsonFormPage extends StatefulWidget { final List<dynamic> jsonData; const JsonFormPage({super.key, required this.jsonData}); @override State<JsonFormPage> createState() => _JsonFormPageState(); } class _JsonFormPageState extends State<JsonFormPage> { late List<TextEditingController> _inputControllers; @override void initState() { super.initState(); // 从JSON数据初始化控制器 _inputControllers = widget.jsonData.map((item) { return TextEditingController(text: item['content'].toString()); }).toList(); } @override void dispose() { // 务必释放控制器资源,避免内存泄漏 for (var controller in _inputControllers) { controller.dispose(); } super.dispose(); } @override Widget build(BuildContext context) { return ListView.builder( itemCount: _inputControllers.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: TextFormField( controller: _inputControllers[index], decoration: InputDecoration( labelText: '输入项 ${index + 1}', border: const OutlineInputBorder(), ), ), ); }, ); } }
方案2:使用状态变量+onChanged回调
将JSON初始值存入状态变量,通过onChanged回调实时更新状态,确保组件重建时读取的是更新后的状态值而非原始JSON值。
class JsonFormPage extends StatefulWidget { final List<dynamic> jsonData; const JsonFormPage({super.key, required this.jsonData}); @override State<JsonFormPage> createState() => _JsonFormPageState(); } class _JsonFormPageState extends State<JsonFormPage> { late List<String> _inputValues; @override void initState() { super.initState(); // 从JSON初始化状态变量 _inputValues = widget.jsonData.map((item) => item['content'].toString()).toList(); } @override Widget build(BuildContext context) { return ListView.builder( itemCount: _inputValues.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: TextFormField( initialValue: _inputValues[index], onChanged: (newValue) { setState(() { _inputValues[index] = newValue; }); }, decoration: InputDecoration( labelText: '输入项 ${index + 1}', border: const OutlineInputBorder(), ), ), ); }, ); } }
关键注意事项
- 禁止直接在
initialValue中使用jsonData[index]['content']这类原始JSON值,否则每次组件重建都会重置输入框内容 - 使用TextEditingController时必须在
dispose方法中释放资源 - 复杂表单场景建议结合Provider、Riverpod等状态管理库统一管理输入状态
内容的提问来源于stack exchange,提问作者Khafah SI
相关产品推荐
相关产品推荐

