如何刷新firebase streambuilder并减少文档读取次数
我正在与弗利特建立一个聊天室,我计划使用firestore。我有一个streambuilder,我将读取的文档数量限制为20个。聊天功能正常,显示最近20条消息。现在,我想在滚动到顶部时添加接下来的20条旧消息 我有一个可行的解决方案,但我不确定它是否是最好的。我最担心的是每次更改限制值时的读取次数。我是在读20篇新文章还是在读40篇新文件?如果我滚动更多,我是否使用60次读取 见下面我的代码如何刷新firebase streambuilder并减少文档读取次数,firebase,flutter,google-cloud-firestore,Firebase,Flutter,Google Cloud Firestore,我正在与弗利特建立一个聊天室,我计划使用firestore。我有一个streambuilder,我将读取的文档数量限制为20个。聊天功能正常,显示最近20条消息。现在,我想在滚动到顶部时添加接下来的20条旧消息 我有一个可行的解决方案,但我不确定它是否是最好的。我最担心的是每次更改限制值时的读取次数。我是在读20篇新文章还是在读40篇新文件?如果我滚动更多,我是否使用60次读取 见下面我的代码 void initState() { maxMessageToDisplay = 20;
void initState() {
maxMessageToDisplay = 20;
_scrollController = ScrollController();
_scrollController.addListener(() {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
setState(() {
maxMessageToDisplay += 20;
});
}
});
super.initState();
}
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('chat').limit(maxMessageToDisplay).orderBy('timestamp', descending: true).snapshots(),
builder: (context, snapshot) {
final messages = snapshot.data.documents;
messages.sort((a, b) => b.data['timestamp'].compareTo(a.data['timestamp']));
var format = new DateFormat("Hm");
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
final messageText = message.data['text'];
final messageSender = message.data['sender'];
final messagePhoto = message.data['photo'];
final messageUserId = message.data['uid'];
final messageTime = format.format(DateTime.fromMillisecondsSinceEpoch(message.data['timestamp'], isUtc: false));
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
photo: messagePhoto,
time: messageTime,
userId: messageUserId,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
controller: _scrollController,
reverse: true,
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
children: messageBubbles,
),
);
},
);
}
}
void initState(){
maxMessageToDisplay=20;
_scrollController=scrollController();
_scrollController.addListener((){
if(_scrollController.position.pixels==_scrollController.position.maxScrollExtent){
设置状态(){
maxMessageToDisplay+=20;
});
}
});
super.initState();
}
小部件构建(构建上下文){
返回流生成器(
流:_firestore.collection('chat').limit(maxMessageToDisplay).orderBy('timestamp',降序:true).snapshots(),
生成器:(上下文,快照){
最终消息=snapshot.data.documents;
messages.sort((a,b)=>b.data['timestamp'].compareTo(a.data['timestamp']);
var格式=新的日期格式(“Hm”);
列表messageBubbles=[];
for(消息中的var消息){
final messageText=message.data['text'];
final messageSender=message.data['sender'];
final messagePhoto=message.data['photo'];
final messageUserId=message.data['uid'];
final messageTime=format.format(DateTime.fromsmiclicondssinceepoch(message.data['timestamp'],isUtc:false));
final messageBubble=messageBubble(
发件人:messageSender,
text:messageText,
照片:messagePhoto,,
时间:messageTime,,
userId:messageUserId,
);
messageBubbles.add(messageBubble);
}
扩大回报(
子:ListView(
控制器:\ u滚动控制器,
相反:是的,
填充:边缘组。对称(垂直:10.0,水平:10.0),
孩子们:泡泡,
),
);
},
);
}
}
通过修改流生成器中使用的流,您应该能够做到这一点
您应该在两个源之间创建一个组合流,并在每次源带来新数据时推送新值。为此,您可以使用rxDart
插件中的BehaviorSubjects
(这很简单,而且比标准流要好一点,尽管您可以使用标准dart流做任何事情)
这是一个示例代码:
List<FireStoreItem> fireStoreItems = [];
BehaviorSubject<List<FireStoreItem>> OlderItemsStream = new BehaviorSubject<List<FireStoreItem>>():
BehaviorSubject<List<FireStoreItem>> finalItemsStream = Rx.combileLatest2(
_firestore.collection('chat').limit(maxMessageToDisplay).orderBy('timestamp', descending: true).snapshots(),
OlderItemsStream, (a,b)=>a.addAll(b))
scrollController.addListener(() {
if(scrollController.position.atEdge){
//create a fireStore call and add the resulting data to the olderItems stream
FireStoreCall().then((data){
OlderItemsStream.add(oldMessages);
});
}
});
注意:scrollController应该与
列表视图中使用的相同,如果侦听器未断开连接超过30分钟,您不必担心,因为Firebase只计算文档更改时的新读取。
因此,在您的情况下,如果您已经阅读了20个文档,那么用户滚动并获得20个以上的文档,您将只有40次而不是60次阅读。
您可以阅读有关firebase计费的更多信息我模拟了2个滚动条,我可以确认读取次数为60次(20条初始消息+20+20)@mactrix,这样您就可以确认它不会重新加载已经存在的消息了?我正在使用您的解决方案,这是我能找到的唯一一个真正具有分页实时功能的解决方案!