Reputation: 61
I'm currently building an application that displays markers on a Google Map. The location of the markers is being pulled from a Firestore database. Currently, I am successfully retrieving and displaying all markers. However, I need to update the icon of each marker based on their boolean value in the database.
Here is how I am currently displaying the markers.
I create the map in the main build:
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: mapToggle
? GoogleMap(
onMapCreated: onMapCreated,
compassEnabled: false,
polylines: route,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 12),
markers: markers,
)
: Center(
child: Text('Loading... Please wait...',
style: TextStyle(fontSize: 20.0)),
)),
Then I call this function in the initState to grab my markers:
chargePoints() {
_database.collection('charge_points').getDocuments().then((docs) {
if (docs.documents.isNotEmpty) {
for (int i = 0; i < docs.documents.length; i++) {
initMarker(docs.documents[i].data, docs.documents[i].documentID);
}
}
});
Finally, the initMarker function adds each marker to the Set marker, taken by the Google Map instance:
void initMarker(chargePoint, documentID) {
var markerIdVal = documentID;
final MarkerId markerId = MarkerId(markerIdVal);
// Creating a new Charge Point Marker
final Marker marker = Marker(
markerId: markerId,
icon: markerIcon,
position: LatLng(chargePoint['location'].latitude,
chargePoint['location'].longitude),
infoWindow: InfoWindow(
title: chargePoint['name'], snippet: chargePoint['type']),
onTap: () {
findBookings(context, chargePoint, documentID);
});
setState(() {
markers.add(marker);
});
So my question is; how can I return this data as a Stream, and provide a listener that updates the respective marker icon, when the "occupied" field has been changed?
Upvotes: 1
Views: 3424
Reputation: 61
Okay, I got a solution!
I'm now returning a StreamBuilder in the main build Widget that takes a Firestore query to return the details of all markers.
I then use the snapshot provided by the stream to intermittently transform the state of all markers set in the initMarker function above.
Additionally, the markers Set is now a Map. This makes more sense for accessing the markers to perform updates.
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
The markers are managed using their MarkerId, which correlates to the documentID of all results returned in the snapshot.
I don't believe this solution is perfect, but I hope I've helped someone out!
StreamBuilder<QuerySnapshot>(
stream: _servicesObj.getChargePoints(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Text('Loading Points');
}
snapshot.data.documents.forEach((change) {
var markerIdVal = change.documentID;
final MarkerId markerId = MarkerId(markerIdVal);
if (change.data['occupied'] == true) {
markers[markerId] = Marker(
markerId: markerId,
icon: pointOccupiedIcon,
position: LatLng(change.data['location'].latitude,
change.data['location'].longitude),
infoWindow: InfoWindow(
title: change.data['name'],
snippet: change.data['type']),
onTap: () {
findBookings(context, change.data, change.documentID);
});
} else {
markers[markerId] = Marker(
markerId: markerId,
icon: pointAvailableIcon,
position: LatLng(change.data['location'].latitude,
change.data['location'].longitude),
infoWindow: InfoWindow(
title: change.data['name'],
snippet: change.data['type']),
onTap: () {
findBookings(context, change.data, change.documentID);
});
}
});
Upvotes: 5