Firebase Flatter/Firestore:如何将项目添加到滚动流中(在完成抓取时保留滚动位置)?

Firebase Flatter/Firestore:如何将项目添加到滚动流中(在完成抓取时保留滚动位置)?,firebase,listview,flutter,stream,stream-builder,Firebase,Listview,Flutter,Stream,Stream Builder,我有一个聊天室(ListView),里面有我只想根据需要加载的消息 因此,当聊天最初加载时,我希望加载最后n条消息,当用户向上滚动时,我也希望获取较旧的消息 每当新消息到达firebase集合时,都应将其添加到列表视图中。我通过使用StreamBuilder实现了这一点,它获取最后n条消息的流,其中n是一个存储在状态中的变量,我可以增加该状态以加载更多消息(它是获取最后n条消息流的函数的参数) 但在我当前的实现中,问题在于,即使在我向上滚动时获取了更多的消息并将其添加到listview,它也会立

我有一个聊天室(
ListView
),里面有我只想根据需要加载的消息

因此,当聊天最初加载时,我希望加载最后n条消息,当用户向上滚动时,我也希望获取较旧的消息

每当新消息到达firebase集合时,都应将其添加到
列表视图中。我通过使用
StreamBuilder
实现了这一点,它获取最后n条消息的流,其中n是一个存储在状态中的变量,我可以增加该状态以加载更多消息(它是获取最后n条消息流的函数的参数)


但在我当前的实现中,问题在于,即使在我向上滚动时获取了更多的消息并将其添加到listview,它也会立即跳回底部(因为listview被重建,而scrollposition没有保留)。如何防止这种情况发生?

此问题与ListView或滚动位置无关。这些是自动保存的。问题必须在代码中的其他地方。查看下面的示例,了解创建列表、添加新项目然后重置列表如何保持滚动位置或移动到正确的位置:

class ListViewStream60521383 extends StatefulWidget {
  @override
  _ListViewStream60521383State createState() => _ListViewStream60521383State();
}

class _ListViewStream60521383State extends State<ListViewStream60521383> {
  List<String> _itemList;

  @override
  void initState() {
    resetItems();
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Expanded(
          child: ListView.builder(
            reverse: true,
            itemCount: _itemList.length,
            itemBuilder: (context, index){
              return Container(
                height: 40,
                child: Text(_itemList[index]),
              );
            },
          ),
        ),
        Row(
          children: <Widget>[
            RaisedButton(
              onPressed: addMoreItems,
              child: Text('Add items'),
            ),
            RaisedButton(
              onPressed: resetItems,
              child: Text('Reset items'),
            )
          ],
        )
      ],
    );
  }

  void addMoreItems(){
    int _currentListCount = _itemList.length;
    setState(() {
      _itemList.addAll(List.generate(60, (index) => 'item ${index + _currentListCount}'));
    });
  }

  void resetItems(){
    setState(() {
      _itemList = List.generate(60, (index) => 'item $index');
    });
  }
}
class ListViewStream60521383扩展StatefulWidget{
@凌驾
_ListViewStream60521383State createState()=>\u ListViewStream60521383State();
}
类_ListViewStream60521383State扩展状态{
列表_itemList;
@凌驾
void initState(){
重置项目();
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回列(
儿童:[
扩大(
子项:ListView.builder(
相反:是的,
itemCount:_itemList.length,
itemBuilder:(上下文,索引){
返回容器(
身高:40,
子项:文本(_itemList[index]),
);
},
),
),
划船(
儿童:[
升起的按钮(
onPressed:addMoreItems,
子项:文本(“添加项”),
),
升起的按钮(
按下:重置项目,
子项:文本(“重置项”),
)
],
)
],
);
}
void addMoreItems(){
int\u currentListCount=\u itemList.length;
设置状态(){
_addAll(List.generate(60,(index)=>'item${index+\u currentListCount}');
});
}
作废重置项目(){
设置状态(){
_itemList=List.generate(60,(index)=>“item$index”);
});
}
}

此问题与ListView或滚动位置无关。这些是自动保存的。问题必须在代码中的其他地方。查看下面的示例,了解创建列表、添加新项目然后重置列表如何保持滚动位置或移动到正确的位置:

class ListViewStream60521383 extends StatefulWidget {
  @override
  _ListViewStream60521383State createState() => _ListViewStream60521383State();
}

class _ListViewStream60521383State extends State<ListViewStream60521383> {
  List<String> _itemList;

  @override
  void initState() {
    resetItems();
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Expanded(
          child: ListView.builder(
            reverse: true,
            itemCount: _itemList.length,
            itemBuilder: (context, index){
              return Container(
                height: 40,
                child: Text(_itemList[index]),
              );
            },
          ),
        ),
        Row(
          children: <Widget>[
            RaisedButton(
              onPressed: addMoreItems,
              child: Text('Add items'),
            ),
            RaisedButton(
              onPressed: resetItems,
              child: Text('Reset items'),
            )
          ],
        )
      ],
    );
  }

  void addMoreItems(){
    int _currentListCount = _itemList.length;
    setState(() {
      _itemList.addAll(List.generate(60, (index) => 'item ${index + _currentListCount}'));
    });
  }

  void resetItems(){
    setState(() {
      _itemList = List.generate(60, (index) => 'item $index');
    });
  }
}
class ListViewStream60521383扩展StatefulWidget{
@凌驾
_ListViewStream60521383State createState()=>\u ListViewStream60521383State();
}
类_ListViewStream60521383State扩展状态{
列表_itemList;
@凌驾
void initState(){
重置项目();
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回列(
儿童:[
扩大(
子项:ListView.builder(
相反:是的,
itemCount:_itemList.length,
itemBuilder:(上下文,索引){
返回容器(
身高:40,
子项:文本(_itemList[index]),
);
},
),
),
划船(
儿童:[
升起的按钮(
onPressed:addMoreItems,
子项:文本(“添加项”),
),
升起的按钮(
按下:重置项目,
子项:文本(“重置项”),
)
],
)
],
);
}
void addMoreItems(){
int\u currentListCount=\u itemList.length;
设置状态(){
_addAll(List.generate(60,(index)=>'item${index+\u currentListCount}');
});
}
作废重置项目(){
设置状态(){
_itemList=List.generate(60,(index)=>“item$index”);
});
}
}

您应该看一看问题指南:您应该看一看问题指南:此代码仅在按下按钮时才将项目添加到列表中,但当新邮件到达集合时,我希望在Streambuilder的流中包含更多文档。该按钮仅表示与接收相同的效果来自流的新数据。目的是一样的。我向您展示的问题不是ListView中信息的显示,而是代码中的其他地方。我想我明白您的观点。保留scrollposition的问题可能是因为我在无状态小部件中有streambuilder,并且每当重建streambuilder时(因为我更改了获取流的查询)。scrollcontroller已重建,没有最后一个scrollposition。我会尝试一下,如果有用的话,把它贴在这里。非常感谢。事实上,我已经根据你的回答找到了我的问题。我很高兴能帮上忙!此代码仅在按下按钮时将项目添加到列表中,但当新消息到达集合时,我希望在Streambuilder的流中包含更多文档。该按钮仅表示从流接收新数据的效果。目的是一样的。我向您展示的问题不是ListView中信息的显示,而是代码中的其他地方。我想我明白您的观点。保留scrollposition的问题可能是因为我在无状态小部件中有streambuilder,并且每当重建streambuilder时(因为我更改了获取流的查询)。scrollcontroller已重建,但没有