google_maps_flutter标记无法更新问题求助(GetX Obx/setState无效)
Flutter GetX Obx + Google Map 标记更新不生效问题解决方案
问题描述
使用GetX的Obx组件在Google Map上展示地点标记列表,首次加载可正常显示所有标记,但清空标记列表并调用更新后,旧标记仍未从地图移除;手动调用setState()也无法同步最新标记列表。
核心问题分析
- HomePage重复创建控制器:
build方法中每次调用Get.put(HomeController(...)),导致UI重建时重复创建/替换控制器实例,状态管理混乱。 - stationsList数据未清空:每次调用
getStationLists时未清除旧站点数据,新请求数据被追加到旧列表,循环添加标记时包含旧数据。 - moveCamera方法冗余添加标记:每次调用
moveCamera都会添加重复的"Current address"标记,造成标记冗余。
解决方案步骤
1. 修复控制器初始化逻辑
将控制器初始化移至initState,避免重复创建控制器:
class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { late HomeController controller; @override void initState() { super.initState(); // 仅在初始化时创建一次控制器 controller = Get.put(HomeController(ApiRepository(ApiBaseHelper()))); } @override Widget build(BuildContext context) { super.build(context); return Scaffold( appBar: AppBar(), body: SafeArea( child: Stack( children: [ Obx( () => controller.isLoading.value ? const AppLoader() : GoogleMap( onTap: (position) { controller.customInfoWindowController.hideInfoWindow!(); }, mapToolbarEnabled: true, initialCameraPosition: CameraPosition( target: controller.mapMarkers.isEmpty ? const LatLng(20.5937, 78.9629) : LatLng( controller.mapMarkers.last.position.latitude, controller .mapMarkers.last.position.longitude), zoom: 15.4736, tilt: 59.440717697143555, bearing: 5.55), mapType: MapType.normal, markers: controller.mapMarkers, circles: { Circle( circleId: const CircleId("id"), center: controller.currentLocation.value, radius: controller.selectedRadius == "Select radius" ? 50000.00 : double.parse(controller.selectedRadius) * 1000, fillColor: Colors.blue.shade200.withOpacity(0.5), strokeColor: Colors.blue.shade100.withOpacity(0.1)) }, onMapCreated: (GoogleMapController mapController) async { if (!controller.myMapController.isCompleted) { controller.myMapController.complete(mapController); controller.customInfoWindowController .googleMapController = await controller.myMapController.future; } else { controller.customInfoWindowController .googleMapController = mapController; } }, ), ), CustomInfoWindow( width: 50.w, controller: controller.customInfoWindowController, ), ], ), ), ); } @override bool get wantKeepAlive => true; }
2. 清空stationsList避免数据累积
在getStationLists方法开头清除旧站点数据,确保仅处理最新请求的站点:
void getStationLists(double latitude, double longitude, String radius) async { isLoading(true); currentLocation(LatLng(latitude, longitude)); mapMarkers.clear(); stationsList.clear(); // 新增:清空旧站点数据 final marker = Marker( markerId: const MarkerId("Current Location"), position: LatLng(latitude, longitude), icon: BitmapDescriptor.defaultMarker, ); mapMarkers.add(marker); try { var requestBody = { "latitude1": "$latitude", "longitude1": "$longitude", "meter": radius, "assetTypeName": "Car" }; var data = await _repo.getStationsList(requestBody); if (data.data!.isNotEmpty) { stationsList.addAll(data.data!); for (var element in stationsList) { double latitude = double.parse(element.latitude!); double longitude = double.parse(element.longitude!); Uint8List markerIcon = await getBytesFromAsset( 'assets/images/lnt_charger_marker.png', 100); final marker = Marker( markerId: MarkerId(element.groupName!), position: LatLng(latitude, longitude), icon: BitmapDescriptor.fromBytes(markerIcon), onTap: () { controller.customInfoWindowController.addInfoWindow!( element.groupSeq == null ? Wrap( children: [ Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.0)), child: Column( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text( element.groupName!, style: TextStyle( fontSize: 10.sp, fontWeight: FontWeight.bold, color: AppColors.textColor), ), ), Padding( padding: const EdgeInsets.only( left: 8.0, bottom: 8.0), child: Text( element.location!, style: TextStyle(fontSize: 10.sp), ), ) ], ), ) ], ) : Wrap(children: [ Container( width: 50.w, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.0)), child: Column( children: [ Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0), child: Text( element.groupName!, style: TextStyle(fontSize: 10.sp), ), ), MaterialButton( onPressed: () {}, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), color: AppColors.primaryColor), child: const Padding( padding: EdgeInsets.all(8.0), child: Text( "Details", style: TextStyle(color: Colors.white), ), ), ), ) ], ), ) ]), LatLng(latitude, longitude)); }, ); mapMarkers.add(marker); } moveCamera(latitude, longitude); isLoading(false); debugPrint("The no of markers is ${mapMarkers.length}"); } else { isLoading(false); AppValidations.showToast("No charging stations found for the location"); } } catch (e) { isLoading(false); AppValidations.showToast(e.toString()); } }
3. 移除moveCamera中的冗余标记
删除moveCamera中重复添加的"Current address"标记:
Future<void> moveCamera(double latitude, double longitude) async { final GoogleMapController controller = await myMapController.future; controller.animateCamera(CameraUpdate.newCameraPosition(CameraPosition( target: LatLng(latitude, longitude), zoom: 7.4736, tilt: 59.440717697143555, bearing: 5.55, ))); }
额外优化建议
- 移除
mapMarkers.refresh():Rx集合在clear()和add()操作后会自动触发Obx更新,无需手动调用。 - 确保
MarkerId唯一:使用站点的唯一标识(如element.groupSeq)作为MarkerId,避免因名称重复导致标记被覆盖。
内容的提问来源于stack exchange,提问作者AkashK
相关产品推荐
相关产品推荐

