Flutter谷歌地图多位置添加自定义Marker图标不生效问题求助
问题原因
- 参数传递逻辑错误:Dart的函数参数是值传递,你定义的
setCustomMarker函数中,给形参mapMarker赋值仅会修改该形参的局部副本,不会同步修改类的成员变量mapMarker1、mapMarker2。相当于你加载好的自定义图标根本没有存到后续要使用的变量中,使用时变量为null,谷歌地图就会自动 fallback 到默认标记图标。 - 异步时序问题:
setCustomMarker是异步函数,你在initState中直接调用后没有等待加载完成,页面渲染GoogleMap组件时,图标还未加载完毕,markers集合中的icon属性仍然是null,自然显示默认图标。
修复方案
- 改造
setCustomMarker函数,直接返回加载完成的BitmapDescriptor对象,而不是尝试通过形参赋值:
Future<BitmapDescriptor> setCustomMarker(String iconPath) async { return await BitmapDescriptor.fromAssetImage( ImageConfiguration.empty, iconPath, ); }
- 合并图标加载和接口请求为一个异步任务,确保所有资源加载完成后再渲染地图:
class _SafeSheltersPageState extends State<SafeSheltersPage> { late Future _loadAllDataFuture; Future<Map> _loadAllRequiredData() async { // 用Future.wait同时执行图标加载和接口请求,提升效率 final asyncResults = await Future.wait([ setCustomMarker('images/map/user_location.png'), setCustomMarker('images/map/safe_shelter.png'), _sheltersFutureBuilder(), // 你原有定义的接口请求方法 ]); return { 'userMarker': asyncResults[0] as BitmapDescriptor, 'shelterMarker': asyncResults[1] as BitmapDescriptor, 'apiData': asyncResults[2], }; } // 你原有代码的sheltersFutureBuilder方法,可以保留不动,重命名为私有更规范 Future _sheltersFutureBuilder() async { CurrentLocation currentLocation = await CurrentLocationUtil().getLocation(); Map<String, Object> data = { 'location': { 'latitude': currentLocation.latitude, 'longitude': currentLocation.longitude, } }; return CallApi().postData(data, 'public/api/getShelterLocations'); } @override void initState() { super.initState(); _loadAllDataFuture = _loadAllRequiredData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Safe Shelters'), centerTitle: true, backgroundColor: Colors.red.shade300, ), body: SafeArea( child: FutureBuilder( future: _loadAllDataFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { final resultMap = snapshot.data as Map; final apiResponse = resultMap['apiData']; String responseBody = apiResponse.body; var data = jsonDecode(responseBody); double userCurrentLatitude = data['current_loc']['latitude']; double userCurrentLongitude = data['current_loc']['longitude']; double nearestShelterLat = double.parse(data['shelters']['nearest_shelter'][0]['latitude']); double nearestShelterLon = double.parse(data['shelters']['nearest_shelter'][0]['longitude']); final Set<Marker> markers = { Marker( markerId: const MarkerId("user-loc"), position: LatLng(userCurrentLatitude, userCurrentLongitude), icon: resultMap['userMarker'] as BitmapDescriptor, infoWindow: const InfoWindow( title: 'You', snippet: 'You are currently here!', ), ), Marker( markerId: const MarkerId("nearest-shelter"), position: LatLng(nearestShelterLat, nearestShelterLon), icon: resultMap['shelterMarker'] as BitmapDescriptor, infoWindow: const InfoWindow( title: 'Nearest Safe Shelter', snippet: 'This is the nearest safe shelter from your location', ), ), }; return GoogleMap( markers: markers, initialCameraPosition: CameraPosition( target: LatLng(userCurrentLatitude, userCurrentLongitude), zoom: 15, ), ); } // 建议加上加载中的占位组件 return const Center(child: CircularProgressIndicator()); }, ), ), ); } }
可选优化
如果出现图标大小在不同设备上显示异常的问题,可以在加载图标时传入设备像素比:
Future<BitmapDescriptor> setCustomMarker(String iconPath) async { return await BitmapDescriptor.fromAssetImage( ImageConfiguration( devicePixelRatio: WidgetsBinding.instance.window.devicePixelRatio ), iconPath, ); }
内容的提问来源于stack exchange,提问作者NewPythoneer
相关产品推荐
相关产品推荐

