Flutter ObjectBox存储对象后读取时status属性为null是何原因?
ObjectBox存储对象后读取status属性为null的问题排查
核心错误原因
你的实体类中status字段为自定义枚举类型TicketStatus,ObjectBox原生不会自动持久化没有配置转换规则的自定义非内置类型。你在内存中创建对象时虽然给status赋了非空值,但执行put存储操作时,ObjectBox直接跳过了这个无法识别类型的字段,没有把值写入数据库。后续从数据库读取对象时,没有持久化数据的status字段自然返回默认值null。
你在实体中已经提前定义了statusAsString字段用于存储枚举的序列化值,但全程没有编写对应的枚举和字符串的转换逻辑,这个字段始终没有被使用。
修复方案
以下两种方案二选一即可:
方案1:手动实现枚举和持久化字段的转换(兼容所有ObjectBox版本,适配你现有代码结构)
给不需要持久化的status字段加@Transient()注解,标记该字段不需要ObjectBox处理,同时编写getter/setter自动在枚举值和可持久化的字符串值之间转换:import 'package:objectbox/objectbox.dart'; @Entity() class UnknownCachedTicketScanEntity implements TicketScanDTOIn{ int id = 0; String? eventId; String? ticketId; String? action; List<String>? eventIdList; bool? offline; String? verificationId; int? timestamp; // 用于持久化枚举的字符串值 String? statusAsString; // 标记该字段不参与数据库持久化 @Transient() TicketStatus? status; // 读取时自动把存储的字符串转为枚举 TicketStatus? get storedStatus { if (statusAsString == null) return null; return TicketStatus.values.byName(statusAsString!); } // 赋值时自动把枚举转为字符串存入持久化字段 set storedStatus(TicketStatus? value) { status = value; statusAsString = value?.name; } UnknownCachedTicketScanEntity({ this.eventId, this.action, this.eventIdList, this.offline, this.ticketId, this.verificationId, this.timestamp, this.statusAsString, TicketStatus? status }) { storedStatus = status; } UnknownCachedTicketScanEntity.fromDTO(TicketScanDTOIn? ticketScanDTOIn, String eventId) { ticketId = ticketScanDTOIn?.ticketId; verificationId = ticketScanDTOIn?.verificationId; // 通过自定义setter赋值,自动同步持久化字段 storedStatus = ticketScanDTOIn?.status; this.eventId = eventId; } @override Map<String, dynamic> toJson() => {}; }后续读取状态时,直接访问
storedStatus就能拿到正确的枚举值,不会出现null问题。方案2:使用高版本ObjectBox的内置枚举支持
如果你使用的是objectbox: ^2.0.0及以上版本,框架已经内置了枚举类型的持久化支持,只需要给枚举字段加@EnumProperty注解,指定存储方式即可,不需要额外写转换逻辑:// 确保TicketStatus是标准Dart枚举 enum TicketStatus { TICKET_NOT_USED, TICKET_USED, // 其余你的枚举值 } @Entity() class UnknownCachedTicketScanEntity implements TicketScanDTOIn{ // 其余字段保持不变 // 给枚举字段加注解,useString设为true用枚举名称存储,设为false用枚举索引存储 @EnumProperty(useString: true) TicketStatus? status; // 其余原有代码不变 }
注意事项
修改完实体类代码后,必须重新执行build命令生成ObjectBox的实体绑定代码,否则修改不会生效:
flutter pub run build_runner build --delete-conflicting-outputs
内容的提问来源于stack exchange,提问作者Valentin Rupp
相关产品推荐
相关产品推荐

