我正在我的移动应用程序中集成聊天功能,并决定使用Firebase实时数据库作为FiRestore的后端安装作为一种降低成本的机制.然而,我遇到了一个问题.关于如何使用Realtime Database而不是Firestore的数据创建无限滚动的文档似乎非常稀少.

下面是我的聊天消息的组织方式.这是我要使用的查询:

FirebaseDatabase.instance
            .ref("messages/${widget.placeID}")
            .orderByChild("timeStamp")

这是我想 for each 结果返回的小部件:

MessageWidget(
  message: message.text,
  id: message.uid,
  name: message.name,
  lastSender: message.lastSender,
  date: message.timeStamp,
  profilePicture: message.profilePicture,
);

Here is the database structure
enter image description here

查询可以工作,并且我已经根据查询的JSON响应编写了MessageWidget.我所需要的就是在查询到达滚动顶部时调用它,并加载更多的MessageWdiget.还要注意的是,这是一个聊天应用程序,用户可以在上面滚动,加载较旧的消息,添加到以前的消息之上.

谢谢!

EDIT:以下是我目前拥有的代码:

Flexible(
  child: StreamBuilder(
    stream: FirebaseDatabase.instance
        .ref("messages/${widget.placeID}")
        .orderByChild("timeStamp")
        .limitToLast(20)
        .onValue,
    builder:
        (context, AsyncSnapshot<DatabaseEvent> snapshot) {
      if (!snapshot.hasData) {
        return const CircularProgressIndicator();
      } else {
        Map<dynamic, dynamic> map =
            snapshot.data!.snapshot.value as dynamic;
        List<dynamic> list = [];
        list.clear();
        list = map.values.toList();
        return Align(
          alignment: Alignment.bottomCenter,
          child: Padding(
            padding: const EdgeInsets.only(bottom: 20),
            child: ListView.builder(
                controller: _scrollController,
                // shrinkWrap: true,
                itemCount: list.length,
                itemBuilder: (context, index) {
                  final json = list[index]
                      as Map<dynamic, dynamic>;
                  final message = Message.fromJson(json);
                  return MessageWidget(
                    message: message.text,
                    id: message.uid,
                    name: message.name,
                    lastSender: message.lastSender,
                    date: message.timeStamp,
                    profilePicture:
                        message.profilePicture,
                  );
                }),
          ),
        );
      }
    },
  ),
),

我的initState

void initState() {
   super.initState();

   _scrollController.addListener(() {
     if (_scrollController.position.atEdge) {
       bool isTop = _scrollController.position.pixels == 0;
       if (isTop) {
         //add more messages

       } else {
         print('At the bottom');
       }
     }
   });
 }

推荐答案

您的代码已经加载了所有消息.


如果您希望加载最大数量的邮件,则需要对您加载的邮件数量进行限制.如果您只想加载最新的消息,您可以使用limitToLast来执行此操作-因为当您按timeStamp值对最新消息进行排序时,它们是最后一条消息.

因此,例如,要仅加载最新的10条消息,您可以使用:

FirebaseDatabase.instance
    .ref("messages/${widget.placeID}")
    .orderByChild("timeStamp")
    .limitToLast(10);

这就给了你最初在应用程序中显示的有限数量的消息.


现在,当滚动到达屏幕顶部时,您需要加载前面的10条消息.要做到这一点,您需要知道屏幕顶部的消息的timeStamp值和键--也就是到目前为止显示的最古老的消息.

有了这两个值,您就可以加载前10个值:

FirebaseDatabase.instance
    .ref("messages/${widget.placeID}")
    .orderByChild("timeStamp")
    .endBefore(timeStampValueOfOldestSeenItem, keyOfOldestSeenItem)
    .limitToLast(10);

这里的数据库再次对timeStamp上的 node 进行排序,然后根据您给出的值找到屏幕顶部的 node ,然后返回紧靠前10个 node .

Flutter相关问答推荐

如何等待抖动S定时器.定期取消?

如何为Android 12及以上设备以及Android 11及以下设备动态处理Splash Screen?如果可能的话没有包裹

壁炉有序在Flutter

在Riverpod ConsumerWidget中使用文本编辑控制器

SingleChildScrollView正在将Container的高度限制为子对象,尽管使用了Expanded Inside Row()

Dexing时出错.将Flutter 升级到3.19.0后

如何在Firebase项目中更改包名称和包ID

如何将 colored颜色 阴影作为默认容器 colored颜色 应用于自定义窗口小工具?

将图标呈现在Flutter 克牌小工具的角落上

来自FirebaseAuth的错误DisplayName和邮箱在Flutter应用程序中给出错误

为什么用户界面不会在Flight中的复选框中更改?

Flutter-Riverpod:如何只从提供者读取一次值

如果有空间则居中CustomScrollView

Flutter ImagePicker - 在 onPressed 中异步获取图像显示 lint 警告

如何从底部导航栏打开 bottomModal 表?

如何在 Flutter 中创建 Facebook 创建帖子屏幕?

如何在椭圆形图像周围添加边框?Flutter

Flutter 中父容器顶部的 Gridview 间距额外区域

Flutter - 如何调用此函数?

我想从 dart 中的字符串中删除符号