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

Dart/Flutter中如何将动态Widget的数据存入列表嵌套的Map列表

解决方案

核心问题是动态创建的DynamicWidget内部的输入控制器父组件无法直接访问,将控制器的持有权上移到父组件即可实现所有动态输入内容的获取。

修改步骤:

  1. 移除原有存储DynamicWidget实例的列表,改为在父组件存储所有动态输入框的控制器,方便直接读取输入内容
  2. 修改DynamicWidget构造,接收外部传入的控制器,不再内部创建
  3. 提交数据时遍历控制器列表,组装为需要的activitiesList结构即可
  4. 修复原有布局错误:ListView内部不能使用Expanded组件,调整为更合理的滚动布局
  5. 新增控制器释放逻辑,避免内存泄漏

完整可运行代码:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:27:05