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