i have to write an app that displays markers from firebase for uni. I managed to get markers created localy to show up but i cant seem to get markers from Firebase working. im guessing it has to do something to do with how im retreiving the data from firebase but i cant find why on my own. I am loading images and creating Cards from firebase but this is different.
I am trying to retreive data from Firebase like this:
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);
}
}
});
}
Then trying to create the markers from the data like this:
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;
});
}
I am Calling the getMarkerData() function in initState():
@override
void initState() {
getMarkerData();
super.initState();
}
and then using the markers in the google maps widget:
GoogleMap(
markers: Set<Marker>.of(markers.values),
myLocationEnabled: true,
myLocationButtonEnabled: true,
mapType: MapType.normal,
initialCameraPosition: _initialCameraPosition,
onMapCreated: _onMapCreated,
),
here is my _onMapCreated function
void _onMapCreated(GoogleMapController mapController) async
{
setState(() {
mapController = mapController;
location.onLocationChanged.listen((l) {
});
});
}
here is the whole code (with collapsed drawer):
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) {});
});
}
}
and a picture of the app for good measure.
CodePudding user response:
Your problem is that getMarkerData() is an async function, but you can't use await to wait for its result in initState, because initState can't be an async function. As a result, the GoogleMap widget will be built before the data of your markers are received.
One common solution is to use a FutureBuilder, see here: get the data using a future and build GoogleMap with fetched marker data only after the data has been received, and meanwhile display a progress indicator.
Note: one could argue that using setState when receiving marker data should work in this case, because the GoogleMap widget will be rebuilt. I'm not 100% sure but according to my memories this approach works only if you change the entire marker set, and does not reflect changes like markers[markerId] = marker;. But you can give it a try if you like, make sure that you first collect all the markers, and in setState you update the entires marker set passed to GoogleMap widget in markers.

