Trier la liste de discussion en fonction du message le plus récent avec Firebase
Je ne sais pas pourquoi je suis resté coincé dans un problème selon lequel la liste de discussion ne trie pas par heure du dernier message ou par message le plus récent. J'ai essayé de stocker timestamp
dans la base de données et l' horodatage orderChildBy mais cela ne fonctionne toujours pas. ne fonctionne pas signifie que la liste n'est pas triée après chaque message et continue d'afficher la liste comme triée après le premier message.
Regardez l'image comment les chats sont désordonnés!

C'est ainsi que j'ai créé chatList firebaseDatabase
dans ChatActiviy sur 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)
}
})
Lors de la récupération de la liste de discussion dans recyclerView, j'essaie d'obtenir les détails des utilisateurs pour chaque utilisateur qui est présenté comme l'enfant de currentUser dans la base de données. (Liste de discussion >> CurrentUserId)
ÉDITÉ
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)
}
}
Et voici le chatListAdapter pour les informations sur les amis
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()
}
}
}
Ceci est l'image de la base de données en temps réel et a une classe de modèle comme ChatList , chaque fois que j'envoie ou reçois un horodatage de message obtient une mise à jour.
et une autre image des utilisateurs dans le firestore et a une classe de modèle en tant qu'utilisateurs .
SOLUTION
J'ai une solution qui fonctionne, ici je crée ou mets à jour un champ en tant que lastMessageTimestamp dans la Firestore
collection Users afin que les utilisateurs puissent maintenant trier par 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) {
}
}
})
Et au moment de la lecture, j'utilise orderBy pour les utilisateurs
val userRef = FirebaseFirestore.getInstance().collection("Users").orderBy("lastMessageTimestamp" , Query.Direction.ASCENDING)
Mais ce n'est pas la solution complète car il semble que je lis et écris le lastMessageTimestamp à chaque fois sur la messagerie, ce qui peut augmenter le Firebase Billing
montant à d'énormes nombres effrayants. donc j'ai encore besoin d'une solution.
Réponses
L'astuce simple est orderBy id du message. Parce que l'identifiant généré par Firebase est basé sur le temps réel + quelques facteurs. Essayons donc de classer par ID au lieu de votre horodatage. (note: juste l'identifiant généré par firebase)