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

Flutter中如何获取对象属性名称列表并动态取值?

Flutter通用网格Widget:动态读取对象属性实现方案

问题背景

我是一名Flutter新手,正在尝试制作一个通用网格Widget,可传入任意对象并动态生成行列。目前已实现特定对象的适配,但需要读取对象的属性名称来动态生成网格列名和对应值,以便该网格能适配客户、商品等各类对象。

示例Client类:

class Client {
  int id;
  String name;
  String mail;

  Client({required this.id, required this.name, required this.mail});
}

需要实现:

  1. 获取对象的字段名称列表(如id、name、mail)
  2. 通过字段名称获取对应值,类似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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:37:33