地图位置移动时更新餐厅标记的Flutter技术求助
问题:地图移动后无法加载新区域的餐厅标记
我通过Google Places API实现了基于当前位置显示附近餐厅的Flutter功能,但手动移动手机地图位置后,新区域的餐厅标记无法加载显示。尝试过用Google Maps的onCameraMove方法更新标记但未成功,恳请协助解决基于新相机位置更新餐厅标记的问题。
import 'package:family_farms_forever/utilities/secrets.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:google_maps_webservice/places.dart'; import 'package:google_maps_flutter_platform_interface/src/types/marker_updates.dart'; void main() => runApp(const MyApp()); final places = GoogleMapsPlaces(apiKey: Secrets.iosApiKey); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: "Market Map", home: Scaffold( appBar: AppBar(title: const Text("My Location")), body: const MyMarketMap()), ); } } class MyMarketMap extends StatefulWidget { const MyMarketMap({super.key}); @override State<StatefulWidget> createState() { return _MyMarketMapState(); } } class _MyMarketMapState extends State<MyMarketMap> { late Future<Position> _currentLocation; late final Set<Marker> _markers = {}; GoogleMapController? _mapController; Timer? _debounceTimer; LatLng? _lastRequestedLocation; @override void initState() { super.initState(); _currentLocation = Geolocator.getCurrentPosition(); } Future<void> _retrieveNearbyRestaurants(LatLng targetLocation) async { if (_lastRequestedLocation != null && Geolocator.distanceBetween( _lastRequestedLocation!.latitude, _lastRequestedLocation!.longitude, targetLocation.latitude, targetLocation.longitude, ) < 500) { return; } _lastRequestedLocation = targetLocation; PlacesSearchResponse response = await places.searchNearbyWithRadius( Location(lat: targetLocation.latitude, lng: targetLocation.longitude), 10000, type: "restaurant"); _markers.removeWhere((marker) => marker.markerId.value != "User Location"); Set<Marker> restaurantMarkers = response.results .map((result) => Marker( markerId: MarkerId(result.name), icon: BitmapDescriptor.defaultMarkerWithHue( BitmapDescriptor.hueAzure), infoWindow: InfoWindow( title: result.name, snippet: "Ratings: ${result.rating?.toString() ?? "Not Rated"}"), position: LatLng( result.geometry!.location.lat, result.geometry!.location.lng))) .toSet(); setState(() { _markers.addAll(restaurantMarkers); }); } void _handleCameraMove(CameraPosition position) { if (_debounceTimer != null) { _debounceTimer!.cancel(); } _debounceTimer = Timer(const Duration(milliseconds: 500), () { _retrieveNearbyRestaurants(position.target); }); } @override Widget build(BuildContext context) { return FutureBuilder( future: _currentLocation, builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasData) { Position snapshotData = snapshot.data; LatLng userLocation = LatLng(snapshotData.latitude, snapshotData.longitude); if (_markers.isEmpty) { _retrieveNearbyRestaurants(userLocation); _markers.add(Marker( markerId: const MarkerId("User Location"), infoWindow: const InfoWindow(title: "User Location"), position: userLocation)); } return GoogleMap( onMapCreated: (controller) => _mapController = controller, myLocationEnabled: true, zoomGesturesEnabled: true, onCameraIdle: () => _handleCameraMove(_mapController!.cameraPosition), initialCameraPosition: CameraPosition( target: userLocation, zoom: 12, ), markers: _markers, ); } else { return const Center(child: Text("Failed to get user location.")); } } return const Center(child: CircularProgressIndicator()); }); } @override void dispose() { _debounceTimer?.cancel(); super.dispose(); } }
关键修复点说明
- 防抖处理:用
Timer实现防抖,避免拖动地图时频繁触发API请求,防止超出调用限制 - 标记清理:每次获取新区域餐厅前,移除旧的餐厅标记(保留用户位置标记),避免标记堆积
- 位置去重:判断当前请求位置与上次请求位置的距离,小于500米则跳过请求,优化性能
- 事件选择:改用
onCameraIdle事件,在地图停止移动后再触发请求,比onCameraMove更合理
内容的提问来源于stack exchange,提问作者Smiles4U
相关产品推荐
相关产品推荐

