Flutter Firebase 无法将标记标记到 google-map

Flutter Firebase cant get markers to google-map

我必须编写一个应用程序来显示来自 firebase for uni 的标记。 我设法让在本地创建的标记显示出来,但我似乎无法从 Firebase 获得标记。我猜这与我如何从 firebase 检索数据有关,但我自己找不到原因。我正在加载图像并从 firebase 创建卡片,但这是不同的。

我正在尝试像这样从 Firebase 检索数据:

getMarkerData() async{
 FirebaseFirestore.instance.collection('buildings').get().then((data){
   if(data.docs.isNotEmpty){
     for(int i = 0; i < data.docs.length; i++){
       initMarker(data.docs[i].data, data.docs[i].id);
     }
   }
 });
}

然后尝试从这样的数据创建标记:

GoogleMapController? mapController;
Location location = new Location();
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};

void initMarker(specify, specifyId) async {
  var markerIdVal = specifyId;
  final MarkerId markerId = MarkerId(markerIdVal);
  final Marker marker = Marker(
    markerId: markerId,
    position: LatLng(specify['location'].latitude, specify['location'].longitude),
    infoWindow: InfoWindow(title: specify['name'], snippet: specify['adresse'])
  );
  setState(() {
    markers[markerId] = marker;
  });
}

我正在调用 initState() 中的 getMarkerData() 函数:

@override
void initState() {
    getMarkerData();
    super.initState();
}

然后使用 google 地图小部件中的标记:

GoogleMap(
  markers: Set<Marker>.of(markers.values),
  myLocationEnabled: true,
  myLocationButtonEnabled: true,
  mapType: MapType.normal,
  initialCameraPosition: _initialCameraPosition,
  onMapCreated: _onMapCreated,
),

这是我的 _onMapCreated 函数

void _onMapCreated(GoogleMapController mapController) async
{
    setState(() {
      mapController = mapController;
      location.onLocationChanged.listen((l) {
      });
    });
}

这是完整的代码(带有折叠的抽屉):

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'package:mobs/routes/all_allert.dart';

//home seite
class Home extends StatefulWidget {
final User user;

const Home({Key? key, required this.user}) : super(key: key);

@override
State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
User? _currentUser = FirebaseAuth.instance.currentUser;

static const _initialCameraPosition = CameraPosition(
target: LatLng(54.332678239573355, 10.180124654249582),
zoom: 16,
);

final list = FirebaseFirestore.instance.collection("buildings");

GoogleMapController? mapController;
Location location = new Location();

Map<MarkerId, Marker> markers = <MarkerId, Marker>{};

void initMarker(specify, specifyId) async {
var markerIdVal = specifyId;
final MarkerId markerId = MarkerId(markerIdVal);
final Marker marker = Marker(
    markerId: markerId,
    position:
        LatLng(specify['location'].latitude, specify['location'].longitude),
    infoWindow:
        InfoWindow(title: specify['name'], snippet: specify['adresse']));
setState(() {
  markers[markerId] = marker;
});
}

getMarkerData() async {
FirebaseFirestore.instance.collection('buildings').get().then((data) {
  if (data.docs.isNotEmpty) {
    for (int i = 0; i < data.docs.length; i++) {
      initMarker(data.docs[i].data, data.docs[i].id);
    }
  }
});
}

@override
void initState() {
getMarkerData();
super.initState();
}

Widget build(BuildContext context) {
return WillPopScope(
  onWillPop: () async => false,
  child: Scaffold(
    appBar: AppBar(
      //titel zeile der home seite
      centerTitle: true,
      title: Visibility(
        child: Text('Hallo ${_currentUser!.displayName}!'),
        maintainSize: false,
        maintainAnimation: true,
        maintainState: true,
        visible: !_currentUser!.isAnonymous,
      ),
      backgroundColor: const Color(0xff08345c),
    ),
    drawer: Drawer(...),
    body: GoogleMap(
      markers: Set<Marker>.of(markers.values),
      myLocationEnabled: true,
      myLocationButtonEnabled: true,
      mapType: MapType.normal,
      initialCameraPosition: _initialCameraPosition,
      onMapCreated: _onMapCreated,
    ),
  ),
);
}

void _onMapCreated(GoogleMapController mapController) async {
setState(() {
  mapController = mapController;
  location.onLocationChanged.listen((l) {});
});
}
}

还有一张应用图片作为衡量标准。

你的问题是 getMarkerData() 是一个 async 函数,但是你不能使用 await 来等待它在 initState 中的结果,因为 initState 不能是 async 函数。因此,GoogleMap 小部件将在收到您的标记数据之前构建。

一个常见的解决方案是使用 FutureBuildersee here:使用 future 获取数据并仅在接收到数据后使用获取的标记数据构建 GoogleMap,并且同时显示一个进度指示器。

注意:有人可能会争辩说在接收标记数据时使用 setState 在这种情况下应该有效,因为 GoogleMap 小部件将被重建。我不是 100% 确定,但根据我的记忆,这种方法只有在你更改整个标记集时才有效,并且不会反映像 markers[markerId] = marker; 这样的更改。但是如果你愿意,你可以试一试,确保你首先收集了所有的标记,然后在 setState 中更新传递给 markers 中的 GoogleMap 小部件的整个标记集。