Simeon
Simeon

Reputation: 781

How to prevent my chats from duplicating themselves whenever someone sends a message in Android Studio firebase

I am designing a simple basic chat app using firebase real time database and i've designed everything well, however, i'm facing one sllight issue. My chats keep duplicating themselves on the inbox page (the page whrere the chats are laid out for a user to select which chat he wants to open and start talking).

I've attached an image of what i mean below. Screenshot of the phone screen

The code i am using to get the chats and display them in the recycler view is given below. I have a directory called Conversations in my DB that saves a user's Id and under it, theres a child of each and every person he chats wit, under which is the last message and a seen boolean.

Database Structure

The code is given below

 convoref = FirebaseDatabase.getInstance().getReference().child("Conversations").child(currentUid);

and then..

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

the fetch convo information functuion is below

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

Any help would be greatly appreciated. i cant seem to figure out why the chat duplicates.

Upvotes: 0

Views: 489

Answers (1)

Chaitanya Chavali
Chaitanya Chavali

Reputation: 853

In your onDataChanged method, you are going through every child of the dataSnapshot. Each child of the data snapshot indicates a particular conversation of that particular currentUid guy. So when you are going through every child of the dataSnapshot you are adding all its children to the listview or recyclerview(I don't know what you are using. But you are adding it to the adapter). So you are adding the old data again and again whenever some new data must be added. Hence-duplicate data.

There are two common solutions.

The first is naive method. Do what you are doing right now. But while adding an item (chat, you will call it in your case, I think) to the adapter, check if it is already present in the container resultConvos. That will prevent you from adding duplicate chats. I am sure it is obvious to you also why this method is inefficient. You are unnecessarily having to go through every conversation of a person. It takes O(n) time for just adding one item.

The second method is the recommended method. Remove all the code of ValueEventListener. Instead use ChildEventListener. I don't know if you are aware of it. Check this.

ChildEventListener has mainly 4 methods instead of onDataChanged. Among that, what you require here is onChildAdded. Just like your onDataChanged, it has one argument- a data snapshot. But this data snapshot contains only the newly added child, whereas the data snapshot in onDataChanged contains the whole data of the conversations of that particular user (that means the whole list). So using the data snapshot provided by onChildAdded you can directly add only that chat to the adapter, which takes O(1) time.

For more about ChildEventListener, read that link I attached

Upvotes: 1

Related Questions