Flutter向Firestore上传Offset数据报错的解决方法
Flutter 上传 Offset 类型数据到 Firestore 报错解决
问题现象
- 基于 CustomPaint 实现简易绘图功能,线条坐标以 Flutter 内置
Offset类型存储,直接将 Offset 实例传入 Firestore 上传接口时触发报错:
Invalid argument: Instance of 'Offset'
- 目标上传数据结构参考:
{ "nickname": "dgh", "point": [ "Offset(110.0, 265.4)", "Offset(110.5, 265.6)", "Offset(110.9, 266.1)", "Offset(111.3, 266.7)" ], "color": "MaterialColor(primary value: Color(0xffff5722))", "width": 5.0 }
- 触发报错的测试代码:
await FirebaseFirestore.instance .collection(COL_ROOMS) .doc(widget.roomKey) .collection(COL_DRAW) .doc() .set({ "name": "test", "offset": Offset(1, 1), // 该行触发类型错误 }) .then((value) => logger.d("upload!")) .catchError((error) => logger.w(error));
报错原因
Firestore 仅支持字符串、数字、布尔、数组、键值对Map、时间戳这类原生可序列化数据类型,无法直接识别 Flutter 框架自定义的 Offset、MaterialColor 等对象实例,直接传入就会抛出参数非法错误。
解决方法
根据后续数据读取的需求,二选一即可:
方案1:按字符串格式存储
如果需要和参考结构一致存为字符串格式,直接调用对象自带的 toString() 方法转换即可,颜色类型也可按同样逻辑处理:
.set({ "name": "test", "nickname": "dgh", "width": 5.0, // 单个Offset转字符串 "offset": const Offset(1, 1).toString(), // Offset列表批量转字符串 "point": points.map((e) => e.toString()).toList(), // 颜色转字符串 "color": brushColor.toString(), })
后续读取数据时,自行解析字符串中的x、y坐标值,即可还原为Offset实例。
方案2:结构化存储(推荐)
将Offset拆分为包含dx、dy两个浮点值的Map存储,无需额外字符串解析,读取还原更方便,也支持Firestore侧的数值查询:
// 单Offset转可序列化Map Map<String, double> _offsetToMap(Offset offset) => { "dx": offset.dx, "dy": offset.dy }; // Offset列表批量转换 List<Map<String, double>> _offsetListToMap(List<Offset> offsets) { return offsets.map(_offsetToMap).toList(); } // 上传时调用 .set({ "name": "test", "nickname": "dgh", "width": 5.0, "offset": _offsetToMap(const Offset(1,1)), "point": _offsetListToMap(points), // 颜色存32位int值,还原比字符串更方便 "color": brushColor.value, })
读取数据时,直接取Map中的dx、dy值即可还原Offset:
Offset _offsetFromMap(Map<String, dynamic> data) { return Offset(data["dx"] as double, data["dy"] as double); }
如果存了颜色的int值,读取时直接调用 Color(colorIntValue) 即可还原为Color实例,无需解析字符串。
内容的提问来源于stack exchange,提问作者Kevin Yang
相关产品推荐
相关产品推荐

