Home > OS >  Flutter Firebase cant get markers to google-map
Flutter Firebase cant get markers to google-map

Time:01-10

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.

screenshot of the map in app

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.

  •  Tags:  
  • Related