0

enter image description here

This is my database. I want to check if a particular uid exists before adding so that I can avoid duplicate entries of the same uid. This is my code. It checks if the uid exists and then returns a boolean. which is parsed into an if statement in another method to add the contact. However, this method only returns false, even if the uid already exists in the contacts. Therefore allowing the adding of the same entry.

enter image description here

The method to check if contact exists.

 public void addContacts(final String emailInput){
    DatabaseReference users;

    users = FirebaseDatabase.getInstance().getReference("users");
    users.orderByChild("email").equalTo(emailInput).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users");
            for (DataSnapshot emailSnapshot : dataSnapshot.getChildren()) {
                String emailData = emailSnapshot.child("email").getValue(String.class);
                final String name = emailSnapshot.child("name").getValue(String.class);
                String role = emailSnapshot.child("role").getValue(String.class);
                if (emailData.equals(emailInput)){
                    key = emailSnapshot.getKey();
                    System.out.println(key);
                    if ((!role.equals(userRole))) {
                        DatabaseReference contactRef = ref.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").child(key);
                        contactRef.addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                                if (!dataSnapshot.child(key).exists()) {
                                    ContactProfile newContact = new ContactProfile(key, name);
                                    ref.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").push().setValue(newContact);
                                    Toast.makeText(Contacts.this, "Contact Added Successfully", Toast.LENGTH_SHORT).show();
                                }
                                else {
                                    Toast.makeText(Contacts.this, "Contact Already Exists", Toast.LENGTH_SHORT).show();
                                }
                            }
                            @Override
                            public void onCancelled(@NonNull DatabaseError databaseError) {

                            }
                        });
                    }
                    else if(key.equals(FirebaseAuth.getInstance().getCurrentUser().getUid())){
                        Toast.makeText(Contacts.this, "You cannot add yourself",Toast.LENGTH_SHORT).show();
                    }
                    else{
                        Toast.makeText(Contacts.this, "Cannot add user. \n They have the same role",
                                Toast.LENGTH_SHORT).show();
                    }
                }
                else {
                    Toast.makeText(Contacts.this, "Cannot add user. \n User does not exist",
                            Toast.LENGTH_SHORT).show();
                }
            }
        }
zkvsl
  • 87
  • 1
  • 7

3 Answers3

0

Although i have no idea about firebase , but the problem might occur due to that you are using method inner class so the scope of value is out of this assignment ,and again you are comparing out of the method inner class so the value=1 will not happen it will always be value=0 so condition will never get true.

suraj
  • 1
  • 1
0

Try this...

DatabaseReference contactRef = userRef.child("Users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").child(key);
 @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()) {
           value = 1;
        }
    }
Sachin Soma
  • 3,432
  • 2
  • 10
  • 18
0

Data is loaded from Firebase asynchronously. It is easiest to see what this means if you place a few log statements:

System.out.println("Before attaching listener");
contactRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        System.out.println("Got data");
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        throw databaseError.toException(); // don't ignore errors
    }
});
System.out.println("After attaching listener");

When you run this code, it prints:

Before attaching listener

After attaching listener

Got data

This is probably not what you expected, but it explains exactly why your code doesn't work: by the time you check if (value.equals(1)){, the onDataChange method hasn't run yet.

As you see there is no way we can return the value from the database. Any return statement outside of onDataChange will run before the data has been loaded. And any return statement we run within onDataChange won't be able to return data to the calling function.

The quickest solution is to move all code that needs the data into the onDataChange method:

private boolean contactExists(final String key){
    DatabaseReference userRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference contactRef = userRef.child("users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").child(key);
    contactRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()){
                ... do what we need to do is the key exists
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
             throw databaseError.toException(); // don't ignore errors
        }
    });
}

If you want to make the approach a bit more reusable, you can define your own callback interface and pass that into your contactExists. For an example of this, see my answer here: getContactsFromFirebase() method return an empty list

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807