【发布时间】:2021-03-06 04:43:38
【问题描述】:
我不知道为什么我遇到了 chatList 没有按最后消息时间或最近消息排序的问题。我尝试将timestamp 存储在数据库中并使用 orderChildBy 时间戳,但它仍然无法正常工作。不工作意味着列表不会在每条消息后排序,并继续将列表显示为在第一条消息之后排序。
看图,聊天是怎么乱的!
这是我在 sendMessage 的 ChatActiviy 中的 firebaseDatabase 中创建 chatList 的方式:
val timeAgo = Date().time
val myTimeMap = HashMap<String, Any?>()
myTimeMap["timestamp"] = timeAgo
myTimeMap["id"] = friendId
val friendTimeMap = HashMap<String, Any?>()
friendTimeMap["timestamp"] = timeAgo
friendTimeMap["id"] = currentUserID
val chatListSenderReference = dbRef.child("ChatList").child(currentUserID).child(friendId)
chatListSenderReference.keepSynced(true)
chatListSenderReference.addListenerForSingleValueEvent(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
if(!p0.exists()){
chatListSenderReference.updateChildren(friendTimeMap)
}
val chatListReceiverReference = dbRef.child("ChatList").child(friendId).child(currentUserID)
chatListReceiverReference.updateChildren(myTimeMap)
}
})
在 recyclerView 中检索聊天列表时,我试图获取每个用户的用户详细信息,这些用户在数据库中显示为 currentUser 的子项。 (聊天列表>>CurrentUserId)
已编辑
private fun retrieveChatList() {
usersChatList = ArrayList()
val userRef = dbRef.child("ChatList").child(currentUserID).orderByChild("timestamp")
userRef.addValueEventListener(object : ValueEventListener
{
override fun onCancelled(error: DatabaseError) {
}
override fun onDataChange(snapshot: DataSnapshot)
{
(usersChatList as ArrayList<String>).clear()
if (snapshot.exists()){
for (dataSnapshot in snapshot.children){
val userUid = dataSnapshot.key
if (userUid != null) {
(usersChatList as ArrayList<String>).add(userUid)
}
}
readChatList()
}
}
})
}
private fun readChatList() {
mUsers = ArrayList()
val userRef = FirebaseFirestore.getInstance().collection("Users")
userRef.get()
.addOnSuccessListener { queryDocumentSnapshots ->
mUsers?.clear()
for (documentSnapshot in queryDocumentSnapshots) {
val user = documentSnapshot.toObject(User::class.java)
for (id in usersChatList!!){
if (user.getUid() == id){
(mUsers as ArrayList<User>).add(user)
}
}
}
retrieveGroupChatList()
chatListAdapter?.notifyDataSetChanged()
chatListAdapter = context?.let { ChatListAdapter(it, (mUsers as ArrayList<User>), true) }
recyclerViewChatList.adapter = chatListAdapter
}.addOnFailureListener { e ->
Log.d(ContentValues.TAG, "UserAdapter-retrieveUsers: ", e)
}
}
这是用于好友信息的 chatListAdapter
private fun friendInfo(fullName: TextView, profileImage: CircleImageView, uid: String) {
val userRef = FirebaseFirestore.getInstance().collection("Users").document(uid)
userRef.get()
.addOnSuccessListener {
if (it != null && it.exists()) {
val user = it.toObject(User::class.java)
Picasso.get().load(user?.getImage()).placeholder(R.drawable.default_pro_pic).into(profileImage)
fullName.text = user?.getFullName()
}
}
}
这是实时数据库的图片,有一个模型类为ChatList,每次发送或接收消息时时间戳都会更新。
还有另一张用户在 Firestore 中的图片,其模型类为 Users。
解决方案
我有一个可行的解决方案,在这里我在Firestore Users 集合中创建或更新一个字段作为 lastMessageTimestamp ,以便用户现在可以按 lastMessageTimestamp 排序。
val timeAgo = Date().time
val myFSMap = HashMap<String, Any?>()
myFSMap["timestamp"] = timeAgo
val friendFSMap = HashMap<String, Any?>()
friendFSMap["timestamp"] = timeAgo
//firebase chatlist references.
val chatListSenderReference = dbRef.child("ChatList").child(currentUserID).child(friendId)
val chatListReceiverReference = dbRef.child("ChatList").child(friendId).child(currentUserID)
//Firestore Users references.
val chatListSenderRef = fStore.collection("Users").document(currentUserID)
val chatListReceiverRef = fStore.collection("Users").document(friendId)
chatListSenderReference.addListenerForSingleValueEvent(object : ValueEventListener{
override fun onDataChange(p0: DataSnapshot) {
if(!p0.exists()){
chatListSenderReference.setValue(friendId)
//update the timestamp in Users collection
chatListSenderRef.update(myFSMap)
}
chatListReceiverReference.setValue(currentUserID)
chatListReceiverRef.update(friendFSMap)
override fun onCancelled(p0: DatabaseError) {
}
}
})
在阅读时,我使用 orderBy 表示用户
val userRef = FirebaseFirestore.getInstance().collection("Users").orderBy("lastMessageTimestamp" , Query.Direction.ASCENDING)
但这不是完整的解决方案,因为似乎我每次在消息传递时都会读取和写入 lastMessageTimestamp,这可以将Firebase Billing 增加到巨大的可怕数字。 所以我仍然需要一个解决方案。
【问题讨论】:
-
@MethkalKhalawi 我试过你的建议,但它的工作原理相同没有区别。我会设置赏金然后尝试回答以获得更多声誉。
-
好吧抱歉@mr.groot有点不清楚,我删除了我的答案,因为它不是你需要的,我调试了你共享的代码,它工作正常,.orderByChild("timestamp ") 工作完美,如果我删除该行,所有项目都将按照保存在 Firebase 数据库中的顺序检索,如果将其添加回时间戳获取的所有项目。
-
我还在 Firebase 控制台中手动更改了一些时间戳,并且排序再次正确。 snapshot.children.forEach 中的每个值都是正确的。因此,只需检查最终的 mUsers 数据,然后再将它们添加到适配器中,它们的顺序是什么,或者在将它们添加到适配器之后您对这些数据做了什么。
-
@MariosP 谢谢,我很感激你的奉献精神,帮助你写了一个非常明确的答案。我现在就试试你的建议。请继续尝试回答这个问题。
标签: android sorting firebase-realtime-database google-cloud-firestore