First, apologies I am a total newb to Flutter, Dart & Firestore and despite trying to follow many tutorials I am stuck.
I am trying to retrieve a Firestore collection record by a specific value.
I have a service dart class which runs the query.
import 'package:cloud_firestore/cloud_firestore.dart';
class WaypointService {
getWaypointById(int wpCheckPointId) {
return FirebaseFirestore.instance
.collection("waypoints")
.where("CheckPoint", isEqualTo: wpCheckPointId)
.get();
}
}
This service is passed an integer from a constant in a constants file. The screen that calls the service is:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:lhgth/services/waypoint_service.dart';
class WaypointScreen extends StatelessWidget {
const WaypointScreen({ super.key, required this.wpFirebaseID });
final int wpFirebaseID;
@override
Widget build(BuildContext context) {
var waypoint;
WaypointService().getWaypointById(wpFirebaseID).then((QuerySnapshot wayPoint) {
if (wayPoint.docs.isNotEmpty) {
waypoint = wayPoint.docs.first.data();
print(waypoint); //##1
}
});
print(waypoint); //##2
return Container(
padding: EdgeInsets.all(8),
child: Scaffold(
backgroundColor: Colors.white,
body: Container(
),
)
);
}
}
The issue I have is that the print statement ##1
is outputting what looks to be a JSON value:
{
Radius: 25,
Long: 50.9491835,
Info: Text,
Lat: 0.7317906,
CheckPoint: 1,
Name: Waypoint Name
}
However, the second print ##2
returns a NULL
and so I am not sure how I would work with the data returned from the query in the view itself.
Any guidance would be helpful.
2
Answers
That’s totally normal, the get() method is an async method you have to wait before it returns the value.
The second print ##2 returns null because it called before the getWaypointById method finishes.
First: make your getWaypointById method as Future like this:
Then: instead of doing tests in the build method, you can test in an external method like this:
Then you can call the test method in the build.
To show the value on the screen you can use FutureBuilder:
The issue you are facing is related to the asynchronous nature of your code. When you use
WaypointService().getWaypointById(wpFirebaseID).then(...)
, it performs an asynchronous operation. Your print(waypoint); //##2 runs before the asynchronous operation is complete, hence waypoint is still null.one Approach can be Using async and await with StatefulWidget
Note: A FutureBuilder widget can help you to build your UI based on the latest snapshot. It will automatically rebuild its UI at the right time when the Future is complete. if UI is not too much complicated you can use initState() for better result.