Joaquín Sosa
Joaquín Sosa

Reputation: 29

Can't read Firebase database, data returns null

I'm trying to get a specific user from the database but I can't, also I would like to check if there is already a node with the same name (uid). I don't want to get the whole list of users and then retrieve one from it because I don't think that's good for perfomance, my idea is to directly get the user from the database

I tried many ways but everything I try returns null, I can't get the values from dataSnapshot. I use an interface to make sure I execute the code after the reading is done

        currentUser = FirebaseAuth.getInstance().getCurrentUser();
        mUserReference = FirebaseDatabase.getInstance().getReference("users/"+currentUser.getUid());
        mUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                user = dataSnapshot.getValue(User.class);

                dataStatus.dataIsLoaded(user);
            }

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

            }
        });
    }

Here the interface

    public interface DataStatus{
        void dataIsLoaded(User user);
    }

And when I try to get the user it shows NullPointerException

            UserUtils userUtils = new UserUtils();

            userUtils.getUser(new UserUtils.DataStatus() {
                @Override
                public void dataIsLoaded(User user) {
                    mUser = user;
                }
            });

User creation, when I call this method I do uid = currentUser.getUid()

    public void createNewUser(String uid, String name, String email, DataStatus dataStatus) {
        mUserReference = mDatabase.child("users").child(uid);
        mUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                user = new User(name, email);
                mDatabase.child("users").child(uid).setValue(user);
                dataStatus.dataIsLoaded(user);
            }

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

            }
        });
    }

Here the rules

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}

Here's how my data base is organized

SOLVED The problem was a piece of code, which I didn't include here, that was trying to get access to the user outside the dataIsLoaded interface method, and as onDataChange is asynchronous the user hadn't been downloaded yet so it was conflicting with the code.

Upvotes: 0

Views: 483

Answers (2)

Zain
Zain

Reputation: 40810

Welcome to SO community

Please use .child() method instead of cascading nodes with "/" as below Also check if the value of the datasnapshot is not null using .exists() method

currentUser = FirebaseAuth.getInstance().getCurrentUser();
mUserReference = FirebaseDatabase.getInstance().getReference.child("users").child(currentUser.getUid());
mUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()) {
            user = dataSnapshot.getValue(User.class);
            dataStatus.dataIsLoaded(user);
        }
    }
    // rest of code

Feel free if you need further support

UPDATE

Please replace your listener with below

currentUser = FirebaseAuth.getInstance().getCurrentUser();
mUserReference = FirebaseDatabase.getInstance().getReference.child("users").child(currentUser.getUid());

Query query = FirebaseDatabase.getInstance().getReference.child("users").orderByKey() 
        .equalTo(currentUser.getUid()); 

query.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) { // dataSnapshot contains set of returned result of the query
            User user = singleSnapshot.getValue(User.class);
            if (user != null) {
                dataStatus.dataIsLoaded(user);
            }
        }
    }
}

Upvotes: 1

Manaf
Manaf

Reputation: 33

Welcome to SO community.

When did you call your function to read the user content?

it might be an asynchronous problem.

To make sure, make a function where the user is the parameter and call it once you read something from the DB (onDataChange).

Plus, did you try to print out what is inside " user " when you read it? if it gives you null, the problem is within the path for sure. If so, use .child("users").child(currentUser.getUid())

Upvotes: 0

Related Questions