我正在使用Firebase实时数据库设计一个简单的基本聊天应用程序,并且我对所有内容的设计都很好,但是,我面临着一个小问题。我的聊天一直在收件箱页面上进行重复(该页面用于安排聊天,以便用户选择要打开的聊天并开始交谈)。
我在下面附上我的意思的图片。Screenshot of the phone screen
我用于获取聊天并将其显示在回收者视图中的代码如下。我的数据库中有一个名为“对话”的目录,该目录保存用户的ID,在该目录下,每个与他聊天的人的孩子都有一个孩子,这是最后一条消息和看到的布尔值。
下面给出代码
convoref = FirebaseDatabase.getInstance().getReference().child("Conversations").child(currentUid);
然后..
public void getConvoIds() {
convoref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for(DataSnapshot convo : dataSnapshot.getChildren()){
boolean isMessageSeen = false;
String lastMessage = "";
if(convo.child("seen").getValue() != null) {
isMessageSeen = (boolean) convo.child("seen").getValue();
}else{
Log.i("nolastseen", "location is null");
}
if(convo.child("lastMessage").getValue() != null) {
lastMessage = convo.child("lastMessage").getValue().toString();
}else{
Log.i("nolastMessage", "location is null");
}
Log.i ("the_convo_partner_key", convo.getKey());
Log.i ("lastseenmessage", lastMessage);
Log.i ("seenstate", String.valueOf(isMessageSeen));
FetchConvoInfo(convo.getKey(), isMessageSeen, lastMessage );
}
}
}
下面是获取convo信息的功能
public void FetchConvoInfo(final String key, final boolean isMessageSeen, final String lastMessage){
FirebaseDatabase.getInstance().getReference().child("Users").child(key).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
boolean chatExists = false;
String username = "";
String thumbnail = "";
String chatPartner;
chatPartner = key;
if(dataSnapshot.child("username").exists()){
username = dataSnapshot.child("username").getValue().toString();
}
if(dataSnapshot.child("thumbnail").exists()){
thumbnail = dataSnapshot.child("thumbnail").getValue().toString();
}
ConvoClass obj= new ConvoClass(chatPartner, username, thumbnail, isMessageSeen, lastMessage);
resultConvos.add(obj);
mConvoAdapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
任何帮助将不胜感激。我似乎无法弄清楚为什么聊天重复。
在onDataChanged
方法中,您正在遍历dataSnapshot
的每个子级。数据快照的每个子对象都指示该特定currentUid
人的特定对话。因此,当您遍历dataSnapshot
的每个子代时,会将其所有子代添加到listview
或recyclerview
中(我不知道您使用的是什么,但是您将其添加到适配器中)。因此,无论何时必须添加一些新数据,您都会一次又一次地添加旧数据。
有两种常见的解决方案。
首先是幼稚的方法。做你现在正在做的事情。但是,当向适配器添加一个项目(聊天,我想您会在情况下称呼它)时,请检查容器resultConvos
中是否已存在该项目。这样可以防止您添加重复的聊天。我相信您也很清楚为什么这种方法效率低下。仅添加一项就需要O(n)时间。
第二种方法是推荐方法。删除ValueEventListener
的所有代码。而是使用ChildEventListener
。我不知道你是否知道。检查this。
ChildEventListener主要具有4种方法,而不是onDataChanged
。其中,您需要的是onChildAdded
。就像您的onDataChanged
,它有一个参数-数据快照。但是此数据快照仅包含新添加的子项,而onDataChanged
中的数据快照包含该特定用户的对话的整个数据(即整个列表)。因此,使用onChildAdded
提供的数据快照,您可以直接作为仅与适配器的聊天,时间为O(1)。
有关ChildEventListener
之间的区别的更多信息,请阅读我附加的链接