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

Flutter Web点击地图新Marker不显示问题求助

问题原因

问题出在Marker的唯一性判断逻辑和Flutter Web端Google Maps组件的更新机制上:

你每次添加新标记时,使用了相同的MarkerId(基于widget.tourStop.title)。而Google Maps Flutter中的Marker类是通过markerId判断相等性的——只要两个Marker的markerId相同,就会被视为同一个对象。当你用新Marker(相同markerId、不同position)替换旧Marker时,虽然_markers集合实例已更新,但Flutter会判定新集合与旧集合的元素“相等”,因此不会触发Google Maps组件的重新渲染,导致地图标记位置不更新。

解决方案

方法一:强制刷新组件(快速修复)

添加一个计数器,给GoogleMap绑定动态key,每次更新标记时递增计数器,迫使组件重建加载新标记:

  1. 在_LocationSelectorState中添加计数器变量:
int _refreshCounter = 0;
  1. 修改addMarker方法:
void addMarker(LatLng point) {
  setState(() {
    _refreshCounter++;
    final newMarker = Marker(
      markerId: MarkerId(widget.tourStop.title as String),
      position: point,
    );
    _markers = <Marker>{newMarker};
  });
  print(point);
  print(_markers.first.position.latitude);
}
  1. 给GoogleMap组件添加key参数:
GoogleMap(
  key: ValueKey(_refreshCounter),
  onTap: (point) => addMarker(point),
  markers: _markers,
  // 保留原有其他参数
)

方法二:用ValueNotifier监听集合变化(优雅方案)

通过ValueNotifier管理标记集合,确保集合变化能被组件精准感知:

  1. 替换_markers为ValueNotifier:
final ValueNotifier<Set<Marker>> _markersNotifier = ValueNotifier({});
  1. 修改initializeMap中的标记初始化逻辑:
Future<void> initializeMap(LatLng? position) async {
  if (position != null) {
    final initMarker = Marker(
      markerId: MarkerId(widget.tourStop.title as String),
      position: position,
    );
    _markersNotifier.value = <Marker>{initMarker};
    final GoogleMapController controller = await _mapController.future;
    controller.animateCamera(CameraUpdate.newLatLngZoom(position, 18));
  }
}
  1. 修改addMarker方法:
void addMarker(LatLng point) {
  final newMarker = Marker(
    markerId: MarkerId(widget.tourStop.title as String),
    position: point,
  );
  _markersNotifier.value = <Marker>{newMarker};
  print(point);
  print(_markersNotifier.value.first.position.latitude);
}
  1. 用ValueListenableBuilder包裹GoogleMap:
ValueListenableBuilder<Set<Marker>>(
  valueListenable: _markersNotifier,
  builder: (context, markers, child) {
    return GoogleMap(
      onTap: (point) => addMarker(point),
      markers: markers,
      mapType: _currentMapType,
      myLocationButtonEnabled: true,
      myLocationEnabled: true,
      initialCameraPosition: CameraPosition(
        target: LatLng(
          _initLoc != null
              ? _initLoc!.latitude
              : locationServicesBloc.currentLocation!.latitude,
          _initLoc != null
              ? _initLoc!.longitude
              : locationServicesBloc.currentLocation!.longitude,
        ),
        zoom: 18,
      ),
      onMapCreated: (GoogleMapController controller) {
        _mapController.complete(controller);
      },
    );
  },
)

方案对比

  • 方法一简单直接,适合快速解决问题;组件重建带来的性能开销在单标记场景下可忽略。
  • 方法二更优雅,通过状态监听精准触发更新,性能更优,适合复杂场景扩展。

内容的提问来源于stack exchange,提问作者user3735816

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:44:58