I am new to Flutter and especially Cloud Firestore. My data is stored as a Map containing another Map in my collection. To keep queries to my database as low as possible, I will store the data in a single document and want to retrieve only the lastest document. The code regarding fetching the data:
Future<Map<dynamic, dynamic>> fetchData() async {
final _firestore = FirebaseFirestore.instance;
late Map<dynamic, dynamic> data;
try {
await _firestore
.collection('collection')
.orderBy('timestamp', descending: true)
.limit(1)
.get()
.then((value) => data = value.docs.first.data());
} catch (e) {
print(e);
}
return data;
}
Firstly, I am wondering whether there is a better way to getting the stored map from the most recent document in my collection?
Secondly,I would like to wait for this to finish and then use a FutureBuilder to show each element of my map as text, for example. At a later stage I was thinking about using a provider called in the initState that can send the data retrieved to various screens. For now, I am simply trying to display the data, but it seems like I am misunderstanding how this works:
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late Future<Map<dynamic, dynamic>> fixtures;
@override
void initState() {
fixtures = _getData();
super.initState();
}
Future<Map<dynamic, dynamic>> _getData() async {
return await fetchData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: FutureBuilder(
future: fixtures,
builder: (BuildContext context,
AsyncSnapshot<Map<dynamic, dynamic>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('loading...'));
} else {
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else {
return Center(child: Text('${snapshot.data!['XY']}'));
}
}
}),
));
}
}
It kind of works this way, but I feel like its not correct. What I don't really understand is how to properly access the data from the snapshot, how to properly store all data, and if there is a better way of doing so. The documentation always simply says snapshot.data but does not actually use the data retrieved to perform any action.
Many thanks in advance.
CodePudding user response:
It looks fine to me, if maybe a bit convoluted.
I'd probably simplify your fetchData
to:
Future<Map<dynamic, dynamic>> fetchData() async {
var value = await FirebaseFirestore.instance
.collection('collection')
.orderBy('timestamp', descending: true)
.limit(1)
.get()
return value.docs.first.data();
}
The changes:
- Removed the
catch
. Since you're not really handling the error, it's best to let it bubble up and only catch errors at the top-level, where you can then centrally log them or for example send them to Crashlytics. - It's often harder to read code that combines
await
andthen.
Use one of the other.