异步函数返回List<LatLng>,接收函数却识别为Future<List<LatLng>>
问题解决方法
核心问题
你在_createMarker函数里调用getLocations(context)时没有使用await,而且这个函数是同步函数(无async修饰),无法直接等待异步结果,所以拿到的还是Future<List<LatLng>>类型,而非实际的List<LatLng>。另外代码里的stores变量也是异步获取的,同样存在这个问题。
解决方案
把组件改成StatefulWidget,用FutureBuilder处理异步数据加载,具体修改如下:
class MapPage extends StatefulWidget { const MapPage({super.key}); @override State<MapPage> createState() => _MapPageState(); } class _MapPageState extends State<MapPage> { late GoogleMapController mapController; final LatLng _center = const LatLng(51.49759646223456, -0.22884194229223435); void _onMapCreated(GoogleMapController controller) { mapController = controller; } // 合并两个异步请求,同时获取位置和店铺名称 Future<Map<String, dynamic>> _fetchData() async { final locations = await buildLocations(context); final stores = await buildStores(context); return {'locations': locations, 'stores': stores}; } Set<Marker> _createMarker(List<LatLng> locations, List<String> stores) { final markers = <Marker>{ Marker( markerId: const MarkerId("marker_1"), position: _center, infoWindow: const InfoWindow( title: "", snippet: "", ), onTap: () => Navigator.push( context, MaterialPageRoute(builder: (context) => const ListPage2()), )), const Marker( markerId: MarkerId("marker_2"), position: LatLng(51.488348, -0.237461), icon: BitmapDescriptor.defaultMarker, ), }; // 遍历生成店铺标记 for (int i = 0; i < locations.length; i++) { if (i < stores.length) { markers.add(Marker( markerId: MarkerId(stores[i]), position: locations[i], )); } } return markers; } Future<List<LatLng>> buildLocations(BuildContext context) async { List<LatLng> locations = []; var collection = FirebaseFirestore.instance.collection('StoreDatabase'); var querySnapshot = await collection.get(); for (var queryDocumentSnapshot in querySnapshot.docs) { Map<String, dynamic> document = queryDocumentSnapshot.data(); // 提取LatLng的经纬度字段,避免类型转换报错 LatLng location = LatLng(document['Location'].latitude, document['Location'].longitude); locations.add(location); } return locations; } Future<List<String>> buildStores(BuildContext context) async { List<String> stores = []; var collection = FirebaseFirestore.instance.collection('StoreDatabase'); var querySnapshot = await collection.get(); for (var queryDocumentSnapshot in querySnapshot.docs) { Map<String, dynamic> document = queryDocumentSnapshot.data(); String store = document['storeName']; stores.add(store); } return stores; } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<Map<String, dynamic>>( future: _fetchData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // 加载中显示转圈 return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { // 加载失败显示错误信息 return Center(child: Text('加载失败: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('暂无数据')); } else { final locations = snapshot.data!['locations'] as List<LatLng>; final stores = snapshot.data!['stores'] as List<String>; return GoogleMap( onMapCreated: _onMapCreated, initialCameraPosition: CameraPosition( target: _center, zoom: 11.0, ), markers: _createMarker(locations, stores), ); } }, ), ); } }
关键改动说明
- 将
mapPage改为StatefulWidget,用于管理异步数据的加载状态。 - 新增
_fetchData函数,合并两个异步请求,减少重复的Firestore查询等待时间。 - 修改
_createMarker,让它直接接收已获取的locations和stores列表,同步生成标记集合。 - 用
FutureBuilder处理异步加载的全流程:等待、错误、无数据、成功,避免UI崩溃。 - 修复
buildLocations中的LatLng转换逻辑,确保从Firestore取出的位置数据能正确转为LatLng类型。
内容的提问来源于stack exchange,提问作者ReDue
相关产品推荐
相关产品推荐

