Flutter中如何获取对象属性名称列表并动态取值?
Flutter通用网格Widget:动态读取对象属性实现方案
问题背景
我是一名Flutter新手,正在尝试制作一个通用网格Widget,可传入任意对象并动态生成行列。目前已实现特定对象的适配,但需要读取对象的属性名称来动态生成网格列名和对应值,以便该网格能适配客户、商品等各类对象。
示例Client类:
class Client { int id; String name; String mail; Client({required this.id, required this.name, required this.mail}); }
需要实现:
- 获取对象的字段名称列表(如
id、name、mail) - 通过字段名称获取对应值,类似
obj.field_name.value的逻辑
解决方案
方法1:手动实现toMap(推荐,适配Flutter全环境)
Flutter发布模式禁用了反射功能,因此最稳妥的方式是让业务类提供属性转Map的方法,同时定义静态字段列表。
1. 改造业务类
给Client添加静态字段列表和toMap方法:
class Client { int id; String name; String mail; // 静态字段名称列表,用于生成列名 static const List<String> fieldNames = ['id', 'name', 'mail']; Client({required this.id, required this.name, required this.mail}); // 将对象转为键值对Map Map<String, dynamic> toMap() { return { 'id': id, 'name': name, 'mail': mail, }; } }
2. 实现通用网格Widget
class GenericGrid<T> extends StatelessWidget { final List<T> items; final List<String> fields; final Map<String, dynamic> Function(T) itemToMap; const GenericGrid({ super.key, required this.items, required this.fields, required this.itemToMap, }); @override Widget build(BuildContext context) { return DataTable( // 生成列 columns: fields.map((field) => DataColumn(label: Text(field))).toList(), // 生成行 rows: items.map((item) { final itemMap = itemToMap(item); return DataRow( cells: fields.map((field) => DataCell(Text(itemMap[field].toString()))).toList(), ); }).toList(), ); } }
3. 使用示例
// 构造测试数据 List<Client> clients = [ Client(id: 1, name: '张三', mail: 'zhangsan@example.com'), Client(id: 2, name: '李四', mail: 'lisi@example.com'), ]; // 渲染通用网格 GenericGrid<Client>( items: clients, fields: Client.fieldNames, itemToMap: (client) => client.toMap(), )
方法2:反射实现(仅开发环境可用)
如果只是开发阶段快速测试,可以用dart:mirrors动态读取属性,但Flutter发布版本会报错,因为该库在发布模式被禁用。
实现代码
import 'dart:mirrors'; // 获取对象的公开非静态字段名称列表 List<String> getObjectFields(Object obj) { final classMirror = reflect(obj).type; return classMirror.declarations.values .whereType<VariableMirror>() .where((vm) => !vm.isStatic && !vm.isPrivate) .map((vm) => MirrorSystem.getName(vm.simpleName)) .toList(); } // 通过字段名获取对象属性值 dynamic getFieldValue(Object obj, String fieldName) { return reflect(obj).getField(Symbol(fieldName)).reflectee; }
使用示例
final client = Client(id: 1, name: '张三', mail: 'zhangsan@example.com'); final fields = getObjectFields(client); // 返回 ['id', 'name', 'mail'] final userName = getFieldValue(client, 'name'); // 返回 '张三'
注意事项
- 若项目需要上线,必须使用方法1,反射无法在Flutter发布版本运行。
- 如需自定义列显示标题,可将
fields改为Map<String, String>类型(键为字段名,值为显示标题),增强灵活性。 - 其他业务类(如商品类)只需遵循同样的
toMap+静态字段列表规范,即可直接复用通用网格Widget。
内容的提问来源于stack exchange,提问作者Code Newbie
相关产品推荐
相关产品推荐

