问题描述
使用与,假设在快照文档中存储了一个引用字段,称为: document ['userRef']
。
Using similar code as flutter's firestore example, suppose there is a reference field stored in a snapshot document, called: document['userRef']
.
首先,如何访问userRef的数据?使用 document ['userRef']。get()。data
或 document ['userRef']。get()。username
我无法访问数据。 ( NoSuchMethodError:类'Future< DocumentSnapshot>'没有实例获取方法'data'
)
First of all, how do I access the data of userRef? Using document['userRef'].get().data
or document['userRef'].get().username
I wasn't able to access the data. (NoSuchMethodError: Class 'Future<DocumentSnapshot>' has no instance getter 'data'
)
我也尝试使用 document ['userRef']。get()。then(...)
,但收到错误: type'Future< dynamic>'不是即使是
。then
的子类型为'String'
I also tried using document['userRef'].get().then(...)
but getting the error: type 'Future<dynamic>' is not a subtype of type 'String'
然后为每个消息再次查找相同的参考吗?这里的数据库是实时更新的,但是不必在ListView中对多个消息进行相同的查找。
Even if .then
would work, wouldn't it then look up the same reference again for each message? Here the database is updated in realtime, but it's unnecessary to make the same lookup for multiple messages in the ListView.
class MessageList extends StatelessWidget {
MessageList({this.firestore});
final Firestore firestore;
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('messages').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
final int messageCount = snapshot.data.documents.length;
return ListView.builder(
itemCount: messageCount,
itemBuilder: (_, int index) {
final DocumentSnapshot document = snapshot.data.documents[index];
// document['userRef'] exists here
return ListTile(
title: Text(document['message'] ?? '<No message retrieved>'),
subtitle: Text('Message ${index + 1} of $messageCount'),
);
},
);
},
);
}
}
编辑:
我能够提取使用FutureBuilder嵌套数据,尽管不确定其效率如何。 (这是否可能会将大量冗余请求发送到Firebase?)
I was able to fetch the nested data using FutureBuilder, though not sure how efficient it is. (Wouldn't this possibly send loads of redundant requests to Firebase?)
为存在document ['userRef']的嵌套数据创建小部件:
Creating a widget for the nested data, where document['userRef'] exists:
FutureBuilder(
future: userData(document['userRef']),
builder: (BuildContext context,
AsyncSnapshot<dynamic> uData) {
return Text(uData.data['username']);
},
);
userData函数如下所示:
And the userData function looks like this:
Future<dynamic> userData(DocumentReference user) async {
DocumentSnapshot userRef = await user.get();
return userRef.data;
}
推荐答案
着火与扑扑这样,可以在Streambuilder中使用Streambuilder。也就是说,不要使用FutureBuilder来处理嵌套数据,而是让您等待每个.get请求。
Sticking to the Firebase and Flutter way, it is possible to use a Streambuilder inside a Streambuilder. That is, instead of using a FutureBuilder for the nested data, which makes you wait for each .get request.
(代码未经测试,但其原理已经过测试。 )
(The code is untested, but the principle is tested.)
class MessageList extends StatelessWidget {
MessageList({this.firestore});
final Firestore firestore;
@override
Widget build(BuildContext context) {
Map UserSnapshot = Map(); // create a variable for accessing users by id
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('users').snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> UsersSnapshot) {
// process usersnapshot from list to map
UsersSnapshot.data.documents.forEach((userRecord) {
//print(optionRecord.documentID); // debug
UserSnapshot[userRecord.documentID] = userRecord;
});
// user data can be accessed as soon as there is a reference field or documentID:
// UserSnapshot[document['userRef']]['userName'}
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('messages').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> MessagesSnapshot) {
if (!MessagesSnapshot.hasData) return const Text('Loading...');
final int messageCount = MessagesSnapshot.data.documents.length;
return ListView.builder(
itemCount: messageCount,
itemBuilder: (_, int index) {
final DocumentSnapshot document =
MessagesSnapshot.data.documents[index];
// document['userRef'] exists here
// UserSnapshot[document['userRef']]['userName'} is accessible here
return ListTile(
title:
Text(document['message'] ?? '<No message retrieved>'),
subtitle: Text('Message ${index + 1} of $messageCount'),
);
},
);
},
);
});
}
}
这篇关于如何有效地扑捉Firestore参考字段的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!