Reputation: 29
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
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
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