提问人:felon 提问时间:10/29/2023 更新时间:10/29/2023 访问量:36
Firestore 分页文档列表在 Flutter 中的奇怪行为
Firestore paginated document list weird behaviour in Flutter
问:
我是 Flutter 的新手,正在构建一个聊天应用程序来练习 firestore。我已经为数据实现了分页,但我看到了奇怪的行为,目前没有解决方案。当我同步文档列表时,它们以完美的顺序列出。但是当我将应用程序长时间置于后台,然后将其拉到前台时,某些项目的顺序不正确。我已经多次看到这种情况发生,如果应用程序在后台并且列表在 firestore 上更新并且我将应用程序放在前台,则一些以前同步的消息会出现在列表的末尾,例如,如果我同步 1,2,3,4,5,6,7 的列表并将应用程序置于后台并重新打开它,那么有时数据看起来像 1,2,4,5,6,7,3。我正在附上用于它的代码。
聊天小部件:
@override
initState() {
super.initState();
.....
_chatViewModel.getMessages();
_scrollController.addListener(_scrollListener);
}
.............
void _scrollListener() async {
_chatViewModel.getOldMessages(_scrollController.position.pixels,
_scrollController.position.maxScrollExtent);
}
.............
child: StreamBuilder(
stream: _chatViewModel.messageStream,
builder: (context, snapshot) =>_setListWidget(snapshot))
.............
Widget _setListWidget(AsyncSnapshot<List<MessageV2>> snapshot) {
if (snapshot.hasData && snapshot.data != null) {
return ListView.builder(
itemCount: snapshot.data!.length,
controller: _scrollController,
reverse: true,
itemBuilder: (context, index) {
return MessageWidget(msg: snapshot.data![index]);
});
} else {
return Center(child: Text('No data...'));
}
}
ChatView模型:
我最近添加了一个 HashSet 作为故障安全措施来防止这种行为,但仍然会发生。
late Stream<List<MessageV2>> messageStream;
final StreamController<List<MessageV2>> _messageStreamProvidor = StreamController();
final _messageList = <MessageV2>[];
ChatViewModel(){
......
messageStream = _messageStreamProvidor.stream;
_messageStreamProvidor.add(_messageList);
}
getMessages() {
_dbService.messages.listen((list) {
try {
var list1 = <MessageV2>[];
for (var element in list) {
if (!_messageSet.contains(element.id)) {
list1.add(element);
_messageSet.add(element.id);
}
}
_messageList.insertAll(0, list1);
_messageStreamProvidor.add(_messageList);
_viewStateStreamProvidor.add(ViewState.viewVisible);
if (list.isNotEmpty && (list.first.isMe || _count == 0)) {
if (_count == 0) _count++;
_scrollStreamProvidor.add(true);
}
} catch (e) {
print(e);
}
});
}
//Method to fetch the old messages.
getOldMessages(double pixels, double maxScrollExtent) async {
if (pixels == maxScrollExtent && !_dbService.loading) {
_messageLoaderProvidor.add(_dbService.loading);
final list = await _dbService.getOldMessageListSnapshot();
if (list != null && list.isNotEmpty) {
for (var e in list) {
if (!_messageSet.contains(e.id)) {
_messageList.add(e);
_messageSet.add(e.id);
}
}
_messageStreamProvidor.add(_messageList);
_messageLoaderProvidor.add(_dbService.loading);
}
}
}
数据库服务:
Stream<List<MessageV2>> get messages {
return _messageCollection
.orderBy('timestamp', descending: true)
.limit(_messageLimit)
.snapshots()
.map(_messageListFromSnapshot);
}
List<MessageV2> _messageListFromSnapshot(QuerySnapshot snapshot) {
final list = <MessageV2>[];
_lastDoc ??= snapshot.docs.last;
for (var e in snapshot.docChanges) {
switch (e.type) {
case DocumentChangeType.added:
list.add(MessageV2.fromMap(e.doc, uid, true));
print('added');
break;
case DocumentChangeType.modified:
print('modified');
break;
case DocumentChangeType.removed:
print('removed');
break;
}
}
return list;
}
Future<List<MessageV2>?> getOldMessageListSnapshot() async {
if (!loading && _lastDoc != null) {
loading = true;
var data = await _messageCollection
.orderBy('timestamp', descending: true)
.startAfterDocument(_lastDoc!)
.limit(_messageLimit)
.get();
loading = false;
if (data.docs.isNotEmpty) {
_lastDoc = data.docs.last;
return _setChatListFromQuerySnapshot(data);
}
}
loading = false;
return null;
}
当代码停留在前台时,它绝对可以正常工作。我可以完美地发送和接收消息,分页也是正确的。只有当它长时间保持在后台时,它才会开始显示此行为。我已经尝试了多种方法来解决这个问题,但它一直在蔓延。当应用程序在后台设置地理位置时,我是否应该清除流,并在前台重新注册它?我在这里有点无知。
答: 暂无答案
评论