【发布时间】:2020-10-25 08:22:02
【问题描述】:
对不起,我的英语不好,我正在用颤振和 firebase 实时数据库做一个聊天应用程序。我正在尝试进行分页。首先,我加载最后 20 条聊天消息,当用户滚动到聊天顶部时,我想再加载 20 条消息。数据恢复正确,但列表视图没有更新。这是我的代码:
class _ChatState extends State<Chat> {
TextEditingController messageEditingController = new TextEditingController();
ScrollController _scrollController = ScrollController();
bool _showKeyboard = true;
Stream _chats;
List item = [];
var _firebaseRef = FirebaseDatabase().reference().child('chatRoom');
sendMessage() {
if (messageEditingController.text.isNotEmpty) {
_firebaseRef.child(widget.chatRoomId).child("chats").push().set({
"sendBy": widget.user.uid,
"message": messageEditingController.text,
"time": DateTime.now().millisecondsSinceEpoch
});
}
setState(() {
messageEditingController.text = "";
});
}
@override
void initState() {
setState(() {
_chats = _firebaseRef
.child(widget.chatRoomId)
.child("chats")
.limitToLast(20)
.onValue;
});
_scrollController.addListener(() {
if (_scrollController.position.atEdge) {
if (_scrollController.position.pixels == 0) {
} else {
_requestMoreMessages();
}
}
});
super.initState();
}
_requestMoreMessages() async {
List _moreItems =[];
_firebaseRef
.child(widget.chatRoomId)
.child("chats")
.orderByChild("time")
.endAt(item.elementAt(19)["time"])
.limitToLast(20)
.once()
.then((snapshot) {
Map<dynamic, dynamic> map = snapshot.value;
map.forEach((key, data) {
print(data["message"]);
_moreItems.add({
"key": key,
"message": data['message'],
"sendBy": data['sendBy'],
"time": data['time']
});
});
setState(() {
item.addAll(_moreItems);
});
});
}
Widget chatMessages() {
return StreamBuilder(
stream:_chats,
builder: (context, snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
Map data = snapshot.data.snapshot.value;
item = [];
data.forEach((index, data) => item.add({
"key": index,
"message": data['message'],
"sendBy": data['sendBy'],
"time": data['time']
}));
item.sort((b, a) => a["time"].compareTo(b["time"]));
return ListView.builder(
reverse: true,
controller: _scrollController,
itemCount: item.length,
itemBuilder: (context, index) {
return MessageTile(
message: item[index]['message'],
sendByMe: widget.user.uid == item[index]['sendBy'],
time: item[index]['time']);
});
} else {
return Container();
}
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarMain(context, widget.userName, widget.urlFoto, context),
body: Column(
children: <Widget>[
Flexible(
child: chatMessages(),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black26),
borderRadius: BorderRadius.circular(50),
color: Colors.black26),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: !_showKeyboard == true
? Icon(LineIcons.keyboard_o)
: Icon(LineIcons.smile_o),
onPressed: () {
if (MediaQuery.of(context).viewInsets.bottom ==
0) {
SystemChannels.textInput
.invokeMethod('TextInput.show');
}
if (mounted) {
setState(() {
_showKeyboard = !_showKeyboard;
});
}
},
),
SizedBox(
width: 230,
child: TextField(
onTap: () {
if (mounted) {
setState(() {
_showKeyboard = true;
});
}
},
controller: messageEditingController,
style: simpleTextStyle(),
textInputAction: TextInputAction.none,
decoration: InputDecoration(
hintText: "Escribe un mensaje",
hintStyle: TextStyle(
color: Colors.black,
fontSize: 16,
),
),
),
),
],
),
),
ClipOval(
child: Material(
color: Theme.of(context).primaryColorDark,
child: InkWell(
splashColor: Theme.of(context).accentColor,
child: IconButton(
color: Colors.white,
onPressed: () {
sendMessage();
// addMessage();
},
icon: Icon(LineIcons.paper_plane),
),
)),
),
],
),
),
)
],
));
}
}
【问题讨论】:
-
如果你想加载更多消息,我认为你应该使用 'startAfter' 而不是 'endAt'。
-
@konto211541 是云 Firestore 数据库的功能,但我使用的是实时数据库。我使用 'endAt' 获得了正确的数据,但我无法更新列表视图
-
@EduardoAndres 实时数据库和 Firestore 都有
startAt和endAt方法。我不确认您必须使用其他方法,但它确实存在于实时数据库 API 中。
标签: firebase flutter listview firebase-realtime-database