Home > front end >  Firebase Firestore and Google Maps Custom Marker only showing one marker
Firebase Firestore and Google Maps Custom Marker only showing one marker

Time:05-20

I'm trying to use the plugin Custom Marker to show on google maps, I got it close to working but it's only showing one marker from my model when I expect it to show all of them. Why is firestore only showing the one marker, how do I get the full list to show all of the markers instead of just one?

Edit 1: Removed old create marker function, that worked to make normal google map markers. Now all that's left is functioning code, it just only shows one marker instead of the entire list.

Edit 2: After reviewing the initial suggestion below I realize I'm getting a similar error message as to their suggestion.

Edit 3: Working code is at the bottom per suggestion by @Denzel

Unhandled Exception: setState() callback argument returned a Future. E/flutter (31835): The setState() method on _HomePageState#73fe9 was called with a closure or method that returned a Future. Maybe it is marked as "async". E/flutter (31835): Instead of performing asynchronous work inside a call to setState(), first execute the work (without updating the widget state), and then synchronously update the state inside a call to setState().


import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:custom_marker/marker_icon.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter/material.dart';

import '../models/marker_collect_model.dart';

class CustomMarkies extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<CustomMarkies> {
  Set<Marker> list = <Marker>{};
  List<String> listDocuments = [];

  Future<void> readDataFromFirebase() async {
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    CollectionReference<Map<String, dynamic>> collectionReference =
    firestore.collection('2022TABR');
    collectionReference.snapshots().listen((event) {
      List<DocumentSnapshot> snapshots = event.docs;
      for (var map in snapshots) {
        Map<String, dynamic> data =
        map.data() as Map<String, dynamic>; // add this line
        MarkerCollectModel model =
        MarkerCollectModel.fromMap(data); // use data here
        String nameDocument = map.id;
        listDocuments.add(nameDocument);
        setState(() async {
          Random random = Random();
          int i = random.nextInt(10000);
          String idString = 'id$i';
          list.add(Marker(
            markerId: MarkerId(idString),
            icon: await MarkerIcon.downloadResizePicture(
                url: model.urlavatar!, imageSize: 250),
            position: LatLng(model.lat!, model.lng!),
          );
        });
      }
    });
  }
  
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        initialCameraPosition: CameraPosition(target: LatLng(45.4279, -123.6880), zoom: 3),
        markers: list,
      ),
      floatingActionButton: FloatingActionButton.extended(
        label: FittedBox(child: Text('Add Markers')),
        onPressed: () async {
          readDataFromFirebase();
          list.toSet();
          setState(() {});
        },
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

working code

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:custom_marker/marker_icon.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter/material.dart';

import '../models/marker_collect_model.dart';

class CustomMarkies extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<CustomMarkies> {
  Set<Marker> list = <Marker>{};
  List<String> listDocuments = [];

  Future<void> readDataFromFirebase() async {
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    CollectionReference<Map<String, dynamic>> collectionReference =
    firestore.collection('2022TABR');
    collectionReference.snapshots().listen((event) async {
      List<DocumentSnapshot> snapshots = event.docs;
      for (var map in snapshots) {
        Map<String, dynamic> data =
        map.data() as Map<String, dynamic>; // add this line
        MarkerCollectModel model =
        MarkerCollectModel.fromMap(data); // use data here
        String nameDocument = map.id;
        listDocuments.add(nameDocument);
          list.add(Marker(
            markerId: MarkerId(nameDocument),
            icon: await MarkerIcon.downloadResizePicture(
                url: model.urlavatar!, imageSize: 250),
            position: LatLng(model.lat!, model.lng!),
          ));
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        initialCameraPosition: CameraPosition(target: LatLng(45.4279, -123.6880), zoom: 3),
        markers: list,
      ),
      floatingActionButton: FloatingActionButton.extended(
        label: FittedBox(child: Text('Add Markers')),
        onPressed: () async {
          readDataFromFirebase();
          list.toSet();
          setState(() {});
        },
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

CodePudding user response:

    class CustomMarkies extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<CustomMarkies> {
      Set<Marker> list = <Marker>{};
      List<String> listDocuments = [];
    
      /// This [async] here covers for everything within the function,
      /// You can use [await] anywhere you want to
      /// [collectionReference.snapshots()] returns a [Stream], so you [listen] to it
      /// There's no need for [await] because [Stream] handles real-time data
      /// In essence, it would update all it's [listeners] about the new change and this change will take effect in your UI
      Future<void> readDataFromFirebase() async {
        FirebaseFirestore firestore = FirebaseFirestore.instance;
        CollectionReference<Map<String, dynamic>> collectionReference =
            firestore.collection('2022TABR');
        collectionReference.snapshots().listen((event) {
          for (var map in snapshots) {
            Map<String, dynamic> data =
            map.data() as Map<String, dynamic>; // add this line
            MarkerCollectModel model =
            MarkerCollectModel.fromMap(data); // use data here
            String nameDocument = map.id;
            listDocuments.add(nameDocument);
              list.add(Marker(
                markerId: MarkerId(nameDocument),
                icon: await MarkerIcon.downloadResizePicture(
                    url: model.urlavatar!, imageSize: 250),
                position: LatLng(model.lat!, model.lng!),
              ));
          }
        });
      }
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: GoogleMap(
            initialCameraPosition:
                CameraPosition(target: LatLng(45.4279, -123.6880), zoom: 3),
            markers: list,
          ),
          floatingActionButton: FloatingActionButton.extended(
            label: FittedBox(child: Text('Add Markers')),
            onPressed: () async {
// you have to `await readDataFromFirebase()` because it is a future.
              await readDataFromFirebase();
              list.toSet();
              setState(() {});
            },
          ),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
        );
      }
    }

I put the comments to explain further what I meant

  • Related