Flutter使用Animarker无法清除地图标记、clearMarkers方法未定义问题
问题根因
两个核心问题导致标记累加、无法清除:
Completer<GoogleMapController>是异步获取控制器实例的包装对象,本身不存在clearMarkers方法,直接调用必然报错。- Animarker插件内部单独维护了标记动画状态缓存,在原有
_storeMarkers集合上做clear、add操作属于同引用修改,setState触发重建时,插件无法正确对比出标记集合的全量变化,旧标记缓存不会被回收;且Animarker的标记由插件自行绘制维护,原生google_maps_flutter的清标记方法对它无效。
修复方案
按以下步骤调整代码即可解决:
- 修正控制器调用逻辑
不要直接操作_mapController这个Completer实例,需要调用地图控制器方法时,必须先await拿到真实的GoogleMapController实例:// 新增获取真实控制器的方法 Future<GoogleMapController> get _realMapController => _mapController.future; // 调用示例:需要移动视角、操作地图时,在async方法内获取实例 // final controller = await _realMapController; // controller.animateCamera(...); - 重构标记更新逻辑,不要复用旧集合引用
不要在原Set对象上做增删操作,每次切换轮播项时直接生成全新的Set集合赋值给_storeMarkers,保证状态对比时能检测到集合的完整变化:// 先定义一个变量记录当前选中的门店id,用于绑定组件key String? _currentShowStoreId; void _carouselCallback(Product product) { _currentShowStoreId = product.store?.id; // 直接生成新Set替换原有集合,不要在旧集合上clear/add _storeMarkers = { RippleMarker( markerId: MarkerId('${product.store?.id}'), alpha: 1, icon: _storePin ?? BitmapDescriptor.defaultMarker, position: LatLng(product.store?.lat ?? 0, product.store?.long ?? 0), ripple: false, onTap: () { if (product.store != null) { _carouselModePinCallback(product.store); } }, ) }; _moveToStore(product.store); setState(() {}); } - 给Animarker组件绑定值Key,强制切换标记时重置内部状态
给Animarker加和当前展示门店绑定的Key,切换轮播项时Key变化会触发组件重建,自动清空内部缓存的旧标记,从根源避免累加问题:Animarker( // 绑定和当前展示内容关联的key key: ValueKey('animarker_store_${_currentShowStoreId ?? "init"}'), mapId: _mapController.future.then<int>((value) => value.mapId), rippleRadius: 0.6, //[0,1.0] range, how big is the circle rippleColor: Colors.grey, // Color of fade ripple circle rippleDuration: Duration(milliseconds: 2500), markers: _storeMarkers, // 本身是Set类型,不需要额外调用toSet() runExpressAfter: 1, // 其余原有配置参数保持不变 )
注意:不要尝试调用GoogleMapController原生的标记清除方法处理Animarker的标记,这类标记由插件独立绘制管理,原生方法无法识别,反而会造成状态错乱。
内容的提问来源于stack exchange,提问作者Illan Maman
相关产品推荐
相关产品推荐

