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
小部件将在收到您的标记数据之前构建。
一个常见的解决方案是使用 FutureBuilder
、see here:使用 future 获取数据并仅在接收到数据后使用获取的标记数据构建 GoogleMap
,并且同时显示一个进度指示器。
注意:有人可能会争辩说在接收标记数据时使用 setState
在这种情况下应该有效,因为 GoogleMap
小部件将被重建。我不是 100% 确定,但根据我的记忆,这种方法只有在你更改整个标记集时才有效,并且不会反映像 markers[markerId] = marker;
这样的更改。但是如果你愿意,你可以试一试,确保你首先收集了所有的标记,然后在 setState
中更新传递给 markers
中的 GoogleMap
小部件的整个标记集。
我必须编写一个应用程序来显示来自 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
小部件将在收到您的标记数据之前构建。
一个常见的解决方案是使用 FutureBuilder
、see here:使用 future 获取数据并仅在接收到数据后使用获取的标记数据构建 GoogleMap
,并且同时显示一个进度指示器。
注意:有人可能会争辩说在接收标记数据时使用 setState
在这种情况下应该有效,因为 GoogleMap
小部件将被重建。我不是 100% 确定,但根据我的记忆,这种方法只有在你更改整个标记集时才有效,并且不会反映像 markers[markerId] = marker;
这样的更改。但是如果你愿意,你可以试一试,确保你首先收集了所有的标记,然后在 setState
中更新传递给 markers
中的 GoogleMap
小部件的整个标记集。