Sort chat-list by the most recent message with firebase

拥有回忆 提交于 2020-12-10 08:35:03

问题


I don't know why I got stuck in a problem that the chatList is not sorting by the last message time or by the most recent message. I have tried storing timestamp in the database and orderChildBy timestamp but it still not working. not working means the list get not sort after every message and keep showing the list as the sorted after first message.

Look at the image how chats are disordered!

This is the way I created chatList in the firebaseDatabase in ChatActiviy on sendMessage:

    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)
        }
    })

On retrieving the chatlist in recyclerView, I am trying to get the users details for each userswho is presented as the child of currentUser in database. (Chatlist>>CurrentUserId)

EDITED

  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)
            }

}

And this is the chatListAdapter for friend info

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()
            }
        }
    }

This is the picture of the realtime database and has a model class as ChatList, every time when I send or receive a message timestamp gets an update.

ChatList

and another picture of Users in the firestore and has a model class as Users .

SOLUTION

I have a solution which works, Here i create or update a field as lastMessageTimestamp in the Firestore Users collection so the users now can sort by the 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) {
               }
            }
        })

And at the time of reading, I use orderBy for Users

 val userRef = FirebaseFirestore.getInstance().collection("Users").orderBy("lastMessageTimestamp" , Query.Direction.ASCENDING)

But It is not the complete solution because it seems like that i read and write the lastMessageTimestamp each time on messaging, which can Increase the Firebase Billing Amount to huge scary numbers. so i still need of a solution.


回答1:


Simple trick is orderBy id of message. Because the id which generated by firebase base on realtime + a few factors. So let's try order by Id instead of ur timestamp. (note: just id which generated by firebase)



来源:https://stackoverflow.com/questions/64968904/sort-chat-list-by-the-most-recent-message-with-firebase

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!