Search code examples
flutterdartgoogle-mapsgoogle-cloud-firestorefuture

Returning List<LatLng> from async function but receiving function still thinks it's a Future<List<LatLng>>


I'm trying to convert a Future<List> into a List so I can use it in a for loop to create markers on google maps. However, when I convert it using an await in one function and return it to another function the second function still thinks it's a Future<List>.

This is my code:

class mapPage extends StatelessWidget {
  late GoogleMapController mapController;

  final LatLng _center = const LatLng(51.49759646223456, -0.22884194229223435);
  // function that converts
  Future<List<LatLng>> getLocations(context) async {
    List<LatLng> locations = await buildLocations(context);
    return locations;
  }

  Set<Marker> _createMarker(context) {
    // attempt to retrieve result of converting function (where error occurs)
    List<LatLng> locations = getLocations(context);

    return {
      Marker(
          markerId: const MarkerId("marker_1"),
          position: _center,
          infoWindow: const InfoWindow(
            title: "",
            snippet: "",
          ),
          onTap: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => listPage2()),
              )),
      Marker(markerId: MarkerId(stores[0]), position: locations[0]),
      const Marker(
        markerId: MarkerId("marker_2"),
        position: LatLng(51.488348, -0.237461),
        icon: BitmapDescriptor.defaultMarker,
      ),
    };
  }

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
          onMapCreated: _onMapCreated,
          initialCameraPosition: CameraPosition(
            target: _center,
            zoom: 11.0,
          ),
          markers: _createMarker(context)),
    );
  }

  @override
  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 location = document['Location'];
      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;
  }
}

Any help is much appreciated!


Solution

  • You need to wait to complete the future(fetch data)

      Future<Set<Marker>> _createMarker(context) async {
        List<LatLng> locations = await getLocations(context);
    

    And use FutureBuilder on body to fetch from _createMarker.

    return Scaffold(
      body: FutureBuilder(
          future: _createMarker(context), //better create state variable
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return GoogleMap(
                  onMapCreated: _onMapCreated,
                  initialCameraPosition: CameraPosition(
                    target: _center,
                    zoom: 11.0,
                  ),
                  markers: snapshot.data??Set());
            }
            return Text("loading");
          },),);
    

    Find more about uisng FutureBuilder