0

I have a Firebase database with a "users" node that has some children and I would like to retrieve the "type" field for a specific user, but I don't know what that user's key would be. I have the following data structure:

users
    -MlHrU3_UgMzrU3IpfOW
       email: 
          "mail@gmail.com"
       tipo: 
           "Aluno"

I tried to do it like this but it always returns null

final String[] tipoUserBD = new String[1];
    database = FirebaseDatabase.getInstance().getReference("users");
    database.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            list.clear();
            for(DataSnapshot dataSnapshot : snapshot.getChildren()){
                if(dataSnapshot.child("email").getValue(String.class).equals(user.getEmail())) {
                    tipoUser[0] = dataSnapshot.child("tipo").getValue().toString();
                }
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
thai.png
  • 3
  • 1
  • "I would like to retrieve the "type" field for a specific user" What **do** you know about that specific user? If you don't know anything about them, the best you can do is read all users. – Frank van Puffelen Oct 06 '21 at 01:50

1 Answers1

1

If you know the key of the user (I know you don't, but let's assume you do in some other case), you can read their profile and log their type with:

database = FirebaseDatabase.getInstance().getReference("users");
database.child("-MlHrU3_UgMzrU3IpfOW").addValueEventListener(new ValueEventListener() {
         //  use the key here
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        Log.d("Tipo", dataSnapshot.child("tipo").getValue(String.class)); //  Specify type here
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        throw error.toException(); //  never ignore errors
    }
});

If you know some property that identifies the user, but not the key, you can use a query to find the matching nodes:

database = FirebaseDatabase.getInstance().getReference("users");
database.orderByChild("email").equalTo("mail@gmail.com").addValueEventListener(new ValueEventListener() {
         //  use the property name and value here
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        for(DataSnapshot dataSnapshot : snapshot.getChildren()){
            Log.d("Tipo", dataSnapshot.child("tipo").getValue(String.class)); //  Specify type here
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        throw error.toException(); //  never ignore errors
    }
});

If you don't know anything about the user, the best you can do is loop over all of them:

database = FirebaseDatabase.getInstance().getReference("users");
database.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        for(DataSnapshot dataSnapshot : snapshot.getChildren()){
            Log.d("Tipo", dataSnapshot.child("tipo").getValue(String.class)); 
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        throw error.toException(); //  never ignore errors
    }
});

The trick you're trying to do with tipoUser[0] is an anti-pattern, as it typically means you're ignoring that data is loaded asynchronously.

As a general (and hard) rules: any code that needs the data from the database will need to be inside onDataChange or be called from there.

For more on this, and examples, see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • it worked to print the user's type in the log, but when I assign this value to a variable of type string, the app gives an error as if the variable was empty :( – thai.png Oct 06 '21 at 21:42
  • It's a bit hard to be certain without seeing the code and error, but my guess is that you're still trying to use the data from the database outside of `onDataChange`/before the `onDataChange` has run. The last section of my answer explains why that won't work, and the links show a lot more on that - and how to implement code inside `onDataChange` or use callbacks. – Frank van Puffelen Oct 06 '21 at 22:18