Dart/Flutter中如何将动态Widget的数据存入列表嵌套的Map列表
解决方案
核心问题是动态创建的DynamicWidget内部的输入控制器父组件无法直接访问,将控制器的持有权上移到父组件即可实现所有动态输入内容的获取。
修改步骤:
- 移除原有存储
DynamicWidget实例的列表,改为在父组件存储所有动态输入框的控制器,方便直接读取输入内容 - 修改
DynamicWidget构造,接收外部传入的控制器,不再内部创建 - 提交数据时遍历控制器列表,组装为需要的
activitiesList结构即可 - 修复原有布局错误:ListView内部不能使用Expanded组件,调整为更合理的滚动布局
- 新增控制器释放逻辑,避免内存泄漏
完整可运行代码:
import 'package:flutter/material.dart'; void main() { runApp(MaterialApp( debugShowCheckedModeBanner: false, home: MyApp(), )); } class MyApp extends StatefulWidget { @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { TextEditingController dutyDescriptionController = TextEditingController(); // 存储所有动态活动输入框的控制器 List<TextEditingController> activityControllers = []; //存储工作班次列表 List<Map<String, dynamic>> dutiesList = []; // 初始为空的活动列表 List<Map<String, dynamic>> activitiesList = []; //添加动态活动输入框,最多3个 addDynamic() { if (activityControllers.length <= 2) { activityControllers.add(TextEditingController()); setState(() {}); } } //提交数据 submitData() { dutiesList.clear(); activitiesList.clear(); // 遍历所有动态输入控制器,组装活动列表 for (var controller in activityControllers) { activitiesList.add({'description': controller.text}); } dutiesList.add({ 'dutyDescription': dutyDescriptionController.text, 'activityDescription': activitiesList, }); print(dutiesList); } @override void dispose() { // 释放所有控制器,避免内存泄漏 dutyDescriptionController.dispose(); for (var controller in activityControllers) { controller.dispose(); } super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Dynamic Widget'), ), body: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: dutyDescriptionController, decoration: const InputDecoration(labelText: 'Duty Description'), ), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: activityControllers.length, itemBuilder: (BuildContext context, int index) => DynamicWidget(controller: activityControllers[index]), ), ElevatedButton( onPressed: addDynamic, child: const Text('Add Activity'), ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { submitData(); }, child: const Icon(Icons.save), ), ); } } // 动态输入组件,接收外部传入的控制器 class DynamicWidget extends StatelessWidget { final TextEditingController controller; const DynamicWidget({super.key, required this.controller}); @override Widget build(BuildContext context) { return TextField( controller: controller, decoration: const InputDecoration(labelText: 'Activity Description'), ); } }
后续扩展说明
如果后续DynamicWidget需要新增其他输入项(如下拉选择、日期选择等),可以自定义数据模型类存储每个动态条目的所有输入值/控制器,逻辑和现有方案完全一致,父组件只需持有所有动态条目的数据实例即可完成内容收集。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

