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

如何基于Device与Group两个模型在Flutter中正确生成层级列表

问题根因

你的代码核心错误是复用了同一个列表对象的引用:
你在全局声明了late List<Device> _listDeviceGroup = [];,每次遍历分组时都调用_listDeviceGroup.clear()清空后填充新数据,再把这个列表存入segmentGroup。Dart中列表是引用类型,你存入map的所有value本质上都是指向同一个列表实例,最后所有key对应的列表都是最后一次遍历分组时的内容,所以无论取哪个key的结果都一致。

修复方案

1. 基础分组修复(解决取值错误问题)

直接在每次遍历分组时创建新的空列表,不要复用全局列表:

late List<Device> devicesList;
late List<Group> groupsList = [];
late Map<int, List<Device>> segmentGroup = LinkedHashMap();

@override
Widget build(BuildContext context) {
  devicesList = widget.model.devices!.values.toList();
  groupsList = widget.model.groups!.values.toList();

  // 每次循环创建新的列表,不要复用全局实例
  for (var group in groupsList) {
    List<Device> groupDevices = [];
    for (var device in devicesList) {
      if (device.groupId == group.id) {
        groupDevices.add(device);
      }
    }
    segmentGroup[group.id!] = groupDevices;
  }

  // 后续使用代码不变
  // ...
}

你也可以用where方法简化写法,效率和双重循环一致,代码更简洁:

for (var group in groupsList) {
  segmentGroup[group.id!] = devicesList.where((d) => d.groupId == group.id).toList();
}

2. 多级层级结构实现(适配多级展开列表需求)

因为你的Group模型本身带有groupId字段,支持父分组嵌套,如果需要实现多层级的树结构,可以按以下方式构建:
首先定义统一的树节点结构,支持分组和设备两种类型:

class TreeNode {
  final int id;
  final String name;
  // 类型:0=分组,1=设备
  final int type;
  // 子节点
  List<TreeNode> children;
  // 原始数据,按需取用
  final dynamic data;

  TreeNode({
    required this.id,
    required this.name,
    required this.type,
    required this.children,
    this.data,
  });
}

然后构建完整的层级树:

List<TreeNode> buildTree() {
  // 先按父分组ID对所有分组做索引
  Map<int?, List<Group>> groupParentMap = {};
  for (var group in groupsList) {
    groupParentMap.putIfAbsent(group.groupId, () => []).add(group);
  }
  // 按分组ID对设备做索引
  Map<int?, List<Device>> deviceGroupMap = {};
  for (var device in devicesList) {
    deviceGroupMap.putIfAbsent(device.groupId, () => []).add(device);
  }

  // 递归构建子节点
  List<TreeNode> buildChildren(int? parentGroupId) {
    List<TreeNode> nodes = [];
    // 先加子分组
    var childGroups = groupParentMap[parentGroupId] ?? [];
    for (var group in childGroups) {
      nodes.add(TreeNode(
        id: group.id!,
        name: group.name ?? '未命名分组',
        type: 0,
        children: buildChildren(group.id),
        data: group,
      ));
    }
    // 再加当前分组下的设备
    var devices = deviceGroupMap[parentGroupId] ?? [];
    for (var device in devices) {
      nodes.add(TreeNode(
        id: device.id!,
        name: device.name ?? '未命名设备',
        type: 1,
        children: [],
        data: device,
      ));
    }
    return nodes;
  }

  // 顶级节点的父groupId一般为null或0,按你的业务逻辑调整即可
  return buildChildren(null);
}

构建完成后拿到的List<TreeNode>就是完整的层级树,可以直接传入多级展开列表组件渲染。

内容的提问来源于stack exchange,提问作者Michail

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:18:06