如何基于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
相关产品推荐
相关产品推荐

