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
相关产品推荐
相关产品推荐

