Flutter Mapbox自定义MyPoint扩展字段无法从Annotation读取问题
问题描述
基于mapbox_maps_flutter实现自定义标注时,自定义了继承自Point的MyPoint类并添加pinnumber字段,初始化标注时pinnumber存在,但在点击回调AnnotationClickListener中,从annotation.geometry解析MyPoint时,pinnumber字段为空。
MyPoint类代码
/// Point, as specified here https://tools.ietf.org/html/rfc7946#section-3.1.2 @JsonSerializable(explicitToJson: true) class MyPoint extends Point { int? pinnumber; MyPoint({ super.bbox, required super.coordinates, this.pinnumber, }); factory MyPoint.fromJson(Map<String, dynamic> json) => _$MyPointFromJson(json); @override Map<String, dynamic> toJson() => super.serialize(_$MyPointToJson(this)); @override MyPoint clone() => MyPoint(coordinates: coordinates.clone(), bbox: bbox?.clone(), pinnumber: pinnumber); @override int get hashCode => Object.hashAll([ type, ...coordinates, if (bbox != null) ...bbox!, if (pinnumber != null) pinnumber!, ]); @override bool operator == (Object other) => other is MyPoint ? coordinates == other.coordinates : false; }
添加标注代码
for (MyPoint pinpoint in pinlist) { pointAnnotationManager?.addAnnotation(imageData, pinpoint,); }
点击回调核心代码片段
@override void onPointAnnotationClick(PointAnnotation annotation) async { // ... 其他逻辑 final end = MyPoint.fromJson((annotation.geometry)!.cast()); // end.pinnumber 为空 // ... 后续逻辑 }
原因分析
Mapbox的PointAnnotation底层仅遵循标准GeoJSON Point结构存储几何信息,只保留type、coordinates、可选bbox这几个字段。自定义的pinnumber字段不会被存入Annotation的geometry对象中,因此从annotation.geometry解析时无法获取该字段。
解决方法
有两种可靠的方案可以保留自定义字段:
方案1:利用PointAnnotation的data字段存储自定义信息
PointAnnotation提供了data字段,专门用于存储额外的自定义数据,Mapbox会完整保留该字段内容。
修改添加标注代码
for (MyPoint pinpoint in pinlist) { final annotation = pointAnnotationManager?.addAnnotation(imageData, pinpoint); // 将自定义的pinnumber存入annotation的data字段 if (annotation != null) { annotation.data = {"pinnumber": pinpoint.pinnumber}; } }
修改点击回调代码
@override void onPointAnnotationClick(PointAnnotation annotation) async { // ... 其他逻辑 final end = MyPoint.fromJson((annotation.geometry)!.cast()); // 从data字段中恢复pinnumber end.pinnumber = (annotation.data as Map<String, dynamic>)["pinnumber"] as int?; // 此时end.pinnumber已包含自定义值 // ... 后续逻辑 }
方案2:本地维护标注ID与MyPoint的映射关系
在页面State中维护一个Map,将每个标注的ID与对应的MyPoint实例绑定,点击时通过ID直接获取完整的MyPoint对象。
在State中定义映射
// 存储标注ID到MyPoint的映射 final Map<String, MyPoint> _annotationMap = {};
修改添加标注代码
for (MyPoint pinpoint in pinlist) { final annotation = pointAnnotationManager?.addAnnotation(imageData, pinpoint); if (annotation != null) { _annotationMap[annotation.id] = pinpoint; } }
修改点击回调代码
@override void onPointAnnotationClick(PointAnnotation annotation) async { // ... 其他逻辑 // 通过标注ID直接获取完整的MyPoint实例 final myPoint = _annotationMap[annotation.id]; if (myPoint != null) { // 使用myPoint即可获取pinnumber final coordinates = await fetchRouteCoordinates(start, myPoint.coordinates, MapsDemo.ACCESS_TOKEN); drawRouteLowLevel(coordinates); } // ... 后续逻辑 }
内容的提问来源于stack exchange,提问作者Securexperts NETwork Google
相关产品推荐
相关产品推荐

