Sortuj listę czatów według najnowszej wiadomości z firebase
Nie wiem, dlaczego utknąłem w problemie polegającym na tym, że lista czatów nie sortuje według czasu ostatniej wiadomości lub najnowszej wiadomości. Próbowałem przechowywać timestamp
w bazie danych i sygnaturę czasową OrderChildBy, ale nadal nie działa. nie działa oznacza, że lista nie jest sortowana po każdej wiadomości i nadal jest wyświetlana jako posortowana po pierwszej wiadomości.
Spójrz na obraz, jak nieuporządkowane są rozmowy!

Tak utworzyłem chatList firebaseDatabase
w ChatActiviy na 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)
}
})
Pobierając listę czatów w recyclinglerView, próbuję uzyskać szczegółowe informacje o użytkownikach dla każdego użytkownika, który jest przedstawiony jako dziecko currentUser w bazie danych. (Lista czatów >> CurrentUserId)
EDYTOWANE
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)
}
}
A to jest chatListAdapter dla informacji o znajomym
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()
}
}
}
To jest obraz bazy danych czasu rzeczywistego i ma klasę modelu jako ChatList , za każdym razem, gdy wysyłam lub odbieram wiadomość, znacznik czasu otrzymuje aktualizację.
i inny obraz użytkowników w Firestore i ma klasę modelu jako Użytkownicy .
ROZWIĄZANIE
Mam rozwiązanie, które działa, tutaj tworzę lub aktualizuję pole jako lastMessageTimestamp w Firestore
kolekcji Users, więc użytkownicy mogą teraz sortować według 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) {
}
}
})
A w momencie czytania używam orderBy for Users
val userRef = FirebaseFirestore.getInstance().collection("Users").orderBy("lastMessageTimestamp" , Query.Direction.ASCENDING)
Ale to nie jest kompletne rozwiązanie, ponieważ wydaje mi się, że za każdym razem czytam i piszę lastMessageTimestamp , co może zwiększyć kwotęFirebase Billing
do ogromnych przerażających liczb. więc nadal potrzebuję rozwiązania.
Odpowiedzi
Prosta sztuczka to kolejność według identyfikatora wiadomości. Ponieważ identyfikator wygenerowany przez firebase opiera się na czasie rzeczywistym + kilka czynników. Spróbujmy więc zamówić według identyfikatora, a nie według daty. (uwaga: tylko identyfikator wygenerowany przez firebase)