[无论何时有人在Android Studio Firebase中发送消息,如何防止我的聊天重复

问题描述 投票:0回答:1

我正在使用Firebase实时数据库设计一个简单的基本聊天应用程序,并且我对所有内容的设计都很好,但是,我面临着一个小问题。我的聊天一直在收件箱页面上进行重复(该页面用于安排聊天,以便用户选择要打开的聊天并开始交谈)。

我在下面附上我的意思的图片。Screenshot of the phone screen

我用于获取聊天并将其显示在回收者视图中的代码如下。我的数据库中有一个名为“对话”的目录,该目录保存用户的ID,在该目录下,每个与他聊天的人的孩子都有一个孩子,这是最后一条消息和看到的布尔值。

Database Structure

下面给出代码

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

任何帮助将不胜感激。我似乎无法弄清楚为什么聊天重复。

android firebase firebase-realtime-database chat
1个回答
0
投票

onDataChanged方法中,您正在遍历dataSnapshot的每个子级。数据快照的每个子对象都指示该特定currentUid人的特定对话。因此,当您遍历dataSnapshot的每个子代时,会将其所有子代添加到listviewrecyclerview中(我不知道您使用的是什么,但是您将其添加到适配器中)。因此,无论何时必须添加一些新数据,您都会一次又一次地添加旧数据。

有两种常见的解决方案。

首先是幼稚的方法。做你现在正在做的事情。但是,当向适配器添加一个项目(聊天,我想您会在情况下称呼它)时,请检查容器resultConvos中是否已存在该项目。这样可以防止您添加重复的聊天。我相信您也很清楚为什么这种方法效率低下。仅添加一项就需要O(n)时间。

第二种方法是推荐方法。删除ValueEventListener的所有代码。而是使用ChildEventListener。我不知道你是否知道。检查this

ChildEventListener主要具有4种方法,而不是onDataChanged。其中,您需要的是onChildAdded。就像您的onDataChanged,它有一个参数-数据快照。但是此数据快照仅包含新添加的子项,而onDataChanged中的数据快照包含该特定用户的对话的整个数据(即整个列表)。因此,使用onChildAdded提供的数据快照,您可以直接作为仅与适配器的聊天,时间为O(1)。

有关ChildEventListener之间的区别的更多信息,请阅读我附加的链接

© www.soinside.com 2019 - 2024. All rights reserved.