Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何刷新firebase streambuilder并减少文档读取次数_Firebase_Flutter_Google Cloud Firestore - Fatal编程技术网

如何刷新firebase streambuilder并减少文档读取次数

如何刷新firebase streambuilder并减少文档读取次数,firebase,flutter,google-cloud-firestore,Firebase,Flutter,Google Cloud Firestore,我正在与弗利特建立一个聊天室,我计划使用firestore。我有一个streambuilder,我将读取的文档数量限制为20个。聊天功能正常,显示最近20条消息。现在,我想在滚动到顶部时添加接下来的20条旧消息 我有一个可行的解决方案,但我不确定它是否是最好的。我最担心的是每次更改限制值时的读取次数。我是在读20篇新文章还是在读40篇新文件?如果我滚动更多,我是否使用60次读取 见下面我的代码 void initState() { maxMessageToDisplay = 20;

我正在与弗利特建立一个聊天室,我计划使用firestore。我有一个streambuilder,我将读取的文档数量限制为20个。聊天功能正常,显示最近20条消息。现在,我想在滚动到顶部时添加接下来的20条旧消息

我有一个可行的解决方案,但我不确定它是否是最好的。我最担心的是每次更改限制值时的读取次数。我是在读20篇新文章还是在读40篇新文件?如果我滚动更多,我是否使用60次读取

见下面我的代码

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,这样您就可以确认它不会重新加载已经存在的消息了?我正在使用您的解决方案,这是我能找到的唯一一个真正具有分页实时功能的解决方案!