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

Flutter GoogleMap中LabelMarker动态更新优化问题求助

问题描述

我通过LabelMarker动态创建Marker并加入集合供GoogleMap组件使用,代码如下:

static Set<Marker> allMarkers = {};
...
allLocationsList.forEach((location) async {
...
allMarkers.addLabelMarker(
            LabelMarker(
              visible: _isItVisible,
              label: _name,
              markerId: MarkerId(_name),
              draggable: false,
              backgroundColor: _amIclose
                  ? Colors.green
                  : Colors.red,
              position: LatLng(_latitude, _longitude),
              onTap: _isItEnabled
                  ? pressButton()
                  : null,
            ),
          );
});
...
return GoogleMap(
            style: _mapStyle,
            gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
              Factory<OneSequenceGestureRecognizer>(
                () => EagerGestureRecognizer(),
              ),
            },
            zoomGesturesEnabled: true,
            tiltGesturesEnabled: false,
            compassEnabled: true,
            rotateGesturesEnabled: true,
            scrollGesturesEnabled: true,
            mapToolbarEnabled: false,
            myLocationEnabled: false,
            myLocationButtonEnabled: false,
            initialCameraPosition: CameraPosition(
              target: _center,
              zoom: 6.2,
            ),
            markers: allMarkers,
            onMapCreated: (GoogleMapController controller) async {
              mapController = controller;
              setState(
                () {
                  mapController?.animateCamera(...);
                },
              );
            },
      );

现在需要通过Stream监听_isItVisible、_isItEnabled、_amIclose三个变量的状态变化,但遇到两个问题:

  • LabelMarker不是Widget,没法给每个Marker单独绑定Stream监听;
  • 用单个Stream全局更新所有Marker会导致大量丢帧甚至崩溃。

需要实现仅更新状态变化的Marker,避免性能损耗。

可行解决方案

1. 给每个位置单独维护状态模型

别把_isItVisible这类状态搞成全局变量,先写个模型类,把每个位置的信息和对应的状态绑在一起:

class LocationMarkerState {
  final String name;
  final LatLng position;
  bool isVisible;
  bool isEnabled;
  bool isClose;

  LocationMarkerState({
    required this.name,
    required this.position,
    required this.isVisible,
    required this.isEnabled,
    required this.isClose,
  });
}

然后用一个StreamController<List<LocationMarkerState>>来管理所有位置的状态流,只有单个位置状态变化时才推送更新,不用每次全量推送。

2. 用StreamBuilder监听,只更改变动的Marker

别直接操作静态的allMarkers,换成StreamBuilder监听状态流,每次流更新时,只对比并修改状态变化的Marker:

StreamBuilder<List<LocationMarkerState>>(
  stream: _locationMarkerStateStream,
  initialData: _initialMarkerStates,
  builder: (context, snapshot) {
    if (!snapshot.hasData) return const SizedBox();
    
    final currentMarkers = Set<Marker>.from(allMarkers);
    final newStates = snapshot.data!;
    
    for (var state in newStates) {
      final markerId = MarkerId(state.name);
      final existingMarker = currentMarkers.firstWhere(
        (m) => m.markerId == markerId,
        orElse: () => LabelMarker(markerId: markerId),
      );
      
      // 检查状态有没有变化,只有变化时才更新
      bool needsUpdate = existingMarker.visible != state.isVisible ||
          (existingMarker as LabelMarker).backgroundColor != (state.isClose ? Colors.green : Colors.red) ||
          existingMarker.onTap != (state.isEnabled ? () => pressButton(state.name) : null);
      
      if (needsUpdate) {
        currentMarkers.remove(existingMarker);
        currentMarkers.addLabelMarker(
          LabelMarker(
            visible: state.isVisible,
            label: state.name,
            markerId: markerId,
            draggable: false,
            backgroundColor: state.isClose ? Colors.green : Colors.red,
            position: state.position,
            onTap: state.isEnabled ? () => pressButton(state.name) : null,
          ),
        );
      }
    }
    
    allMarkers = currentMarkers;
    
    return GoogleMap(
      // 保留原有GoogleMap配置
      markers: allMarkers,
    );
  },
)

3. 优化状态更新的触发逻辑

当某个位置的状态需要修改时,只更新对应LocationMarkerState的属性,再推送更新后的列表:

// 更新单个位置的状态
void updateMarkerState(String name, {bool? isVisible, bool? isEnabled, bool? isClose}) {
  final updatedStates = _currentMarkerStates.map((state) {
    if (state.name == name) {
      return LocationMarkerState(
        name: state.name,
        position: state.position,
        isVisible: isVisible ?? state.isVisible,
        isEnabled: isEnabled ?? state.isEnabled,
        isClose: isClose ?? state.isClose,
      );
    }
    return state;
  }).toList();
  
  _locationMarkerStateStream.add(updatedStates);
  _currentMarkerStates = updatedStates;
}

4. 替换静态集合为成员变量

把allMarkers从静态变量改成State类中的成员变量,避免静态集合带来的内存泄漏和不必要的全局引用问题。同时每次更新只替换需要修改的Marker,不用重建整个集合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:34:52