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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:23:17