如何使用 Flutter 和 Future Builder 从 Cloud Firestore 正确检索数据?
How to properly retrieve data from Cloud Firestore using Flutter and Future Builder?
我是 Flutter 的新手,尤其是 Cloud Firestore。我的数据存储为一个地图,在我的 collection 中包含另一个地图。为了尽可能减少对我的数据库的查询,我会将数据存储在一个文档中,并且只想检索最新的文档。关于获取数据的代码:
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;
}
首先,我想知道是否有更好的方法从我 collection 中的最新文档中获取存储的地图?
其次,我想等待它完成,然后使用 FutureBuilder 将地图的每个元素显示为文本,例如。在稍后的阶段,我正在考虑使用一个在 initState 中调用的提供程序,它可以将检索到的数据发送到各种屏幕。现在,我只是想显示数据,但我似乎误解了它是如何工作的:
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']}'));
}
}
}),
));
}
}
好像是这样的,但我觉得不对。我不太明白的是如何从快照中正确访问数据,如何正确存储所有数据,以及是否有更好的方法。文档总是简单地说 snapshot.data 但实际上并没有使用检索到的数据来执行任何操作。
非常感谢。
我觉得还不错,就是有点绕。
我可能会将您的 fetchData
简化为:
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();
}
变化:
- 删除了
catch
。由于您并没有真正处理错误,因此最好让它冒泡并只在 top-level 处捕获错误,然后您可以在其中集中记录它们,或者例如将它们发送到 Crashlytics。
- 将
await
和 then.
结合使用的代码通常更难阅读。
我是 Flutter 的新手,尤其是 Cloud Firestore。我的数据存储为一个地图,在我的 collection 中包含另一个地图。为了尽可能减少对我的数据库的查询,我会将数据存储在一个文档中,并且只想检索最新的文档。关于获取数据的代码:
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;
}
首先,我想知道是否有更好的方法从我 collection 中的最新文档中获取存储的地图?
其次,我想等待它完成,然后使用 FutureBuilder 将地图的每个元素显示为文本,例如。在稍后的阶段,我正在考虑使用一个在 initState 中调用的提供程序,它可以将检索到的数据发送到各种屏幕。现在,我只是想显示数据,但我似乎误解了它是如何工作的:
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']}'));
}
}
}),
));
}
}
好像是这样的,但我觉得不对。我不太明白的是如何从快照中正确访问数据,如何正确存储所有数据,以及是否有更好的方法。文档总是简单地说 snapshot.data 但实际上并没有使用检索到的数据来执行任何操作。
非常感谢。
我觉得还不错,就是有点绕。
我可能会将您的 fetchData
简化为:
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();
}
变化:
- 删除了
catch
。由于您并没有真正处理错误,因此最好让它冒泡并只在 top-level 处捕获错误,然后您可以在其中集中记录它们,或者例如将它们发送到 Crashlytics。 - 将
await
和then.
结合使用的代码通常更难阅读。