如何从(bool, Map<String, dynamic>)返回值中获取Map内的uid字段
如何从表格组件选中回调中获取uid字段
问题背景
- 表格行选中时会触发
onSelect: onSelected回调,回调接收两个参数:第一个是bool类型选中状态,true代表行选中、false代表取消选中;第二个是Map<String, dynamic>类型的当前行完整数据,回调触发时打印示例:true {uid: 1xorAjA7hRZfOdN3zpkAWI7spgp1, username: awdwa,...} - 需求为读取行数据中的
uid字段,前期尝试直接存储userTable.onSelected返回值、自定义getSelected方法将选中项存入列表后读取,先后触发两类报错:- NoSuchMethodError空动态调用错误
- 类型不匹配错误:期望得到
List<Map<String, dynamic>>类型,实际得到(bool, Map<String, dynamic>) => List<Map<String, dynamic>>函数类型
- 对
(bool, Map<String, dynamic>)这类多参数回调结构的取值逻辑不清晰,无法正确读取Map结构中的uid字段。
原有问题代码
初始onSelected回调实现
List<Map<String, dynamic>> selecteds = []; onSelected(bool value, Map <String, dynamic> item){ print("$value $item "); if (value) { selecteds.add(item); } else { selecteds.removeAt(selecteds.indexOf(item)); } notifyListeners(); }
错误取值方式1
selectedId = userTable.getSelected, print('Uid: '+selectedId[uid])
对应报错信息:
The following NoSuchMethodError was thrown while handling a gesture: '[]' Dynamic call of null. Receiver: Instance of '(bool, Map<String, String>) => dynamic' Arguments: ["M0glOQKUwagZJGOyzVEU1JJgQo23"]
错误取值方式2
尝试将数据存入List<Map<String, dynamic>>类型变量后读取首项,触发类型报错:
Expected a value of type 'List<Map<String, dynamic>>', but got one of type '(bool, Map<String, dynamic>) => List<Map<String, dynamic>>'
自定义getSelected实现
getSelected(bool value, Map <String, dynamic> item){ print("$value $item "); if (value) { selecteds.add(item); return selecteds as List<Map<String, dynamic>>;; } else { selecteds.removeAt(selecteds.indexOf(item)); } notifyListeners(); }
报错核心原因
- 把回调函数本身当成了回调执行后的返回值使用:
userTable.onSelected、userTable.getSelected都是函数对象,直接赋值给变量拿到的是函数引用,不是函数执行后的返回结果,自然会出现类型不匹配、空调用报错。 - 回调参数是组件触发选中事件时自动传入的,不需要手动调用传参,也不能直接拿函数引用当数据读取。
- 自定义
getSelected逻辑存在缺陷:取消选中分支无返回值,函数不同执行路径返回值不一致;选中分支return在notifyListeners()之前,会导致选中状态变更后监听通知无法触发。 - 读取Map字段时key未加引号,
selectedId[uid]会将uid识别为变量而非固定key,也会触发调用错误。
正确实现方案
方案1:直接在onSelected回调内取值(适配单场景快速取值)
不需要额外定义getSelected方法,回调触发时行数据会自动作为第二个参数传入,直接在回调函数内读取uid即可:
List<Map<String, dynamic>> selecteds = []; // 存储当前选中项的uid,可根据业务需要改为列表存储多选uid String? currentSelectedUid; onSelected(bool value, Map<String, dynamic> item){ print("选中状态:$value,行数据:$item"); // 回调触发时直接读取当前行的uid final String uid = item['uid']; if (value) { selecteds.add(item); currentSelectedUid = uid; } else { // 按uid匹配删除,避免indexOf依赖对象相等判断导致的删除失败问题 selecteds.removeWhere((element) => element['uid'] == uid); currentSelectedUid = null; } notifyListeners(); }
后续业务逻辑需要用到uid时,直接读取currentSelectedUid即可;需要获取所有选中项的uid时,遍历selecteds列表读取每项的['uid']字段即可。
方案2:对外暴露选中数据的正确写法
如果需要在组件外部获取选中数据,不要定义带回调参数的getSelected方法,编写无参的取值方法/getter即可:
// 返回所有选中项,用unmodifiable包裹避免外部误修改内部维护的列表 List<Map<String, dynamic>> getSelectedList() { return List.unmodifiable(selecteds); } // 返回第一个选中项的uid String? getFirstSelectedUid() { if (selecteds.isNotEmpty) { return selecteds.first['uid'] as String; } return null; }
外部调用时注意加()执行方法,不要直接引用方法名:
// 正确调用:加()执行方法拿到返回值 final selectedList = userTable.getSelectedList(); final selectedId = userTable.getFirstSelectedUid(); if (selectedId != null) { print('Uid: $selectedId'); }
注意事项:
- 调用方法必须加
(),否则拿到的是函数对象而非返回结果,这是之前类型报错的核心诱因- 读取Map字段时字符串key必须加引号,写为
item['uid']格式,不要直接写item[uid]- 多选场景下删除选中项优先用uid这类唯一标识匹配删除,不要直接用
indexOf,避免Map实例相等判断逻辑不一致导致的删除失败
内容的提问来源于stack exchange,提问作者Hans Sama
相关产品推荐
相关产品推荐

