Chinaedu Onwukwe
Chinaedu Onwukwe

Reputation: 437

Retrieving data from Firebase returns null

I have the stored a User at the Firebase's database. When I want to retrieve the user it is null and I can't explain myself why. My User class simply consists of an String 'email' and String 'name' and boolean 'firstAppUse'.

enter image description here

So I wrote the following method to retrieve a user from database:

public static User getUser(){
    final User [] user = new User[1];
    DatabaseHelper.userDB.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            user[0] = dataSnapshot.getValue(User.class);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

    return user[0];
}

Narrow all expectations user[0] is null. Although the element exists in the database and the reference to it in DatabaseHelper.userDB is just fine:

public class DatabaseHelper {
private static FirebaseDatabase database = FirebaseDatabase.getInstance();
public static DatabaseReference userDB = database.getReference("users/" + FirebaseAuth.getInstance().getCurrentUser().getUid());

} Does anybody see the issue? Thanks in advance.

Upvotes: 0

Views: 1621

Answers (3)

mark922
mark922

Reputation: 1167

When you fetch data from firebase, it is an Asynchronous Task. If you call getUser() and return user[0] then it will always return null because before getting results (DataSnapshot) from firebase you have returned the function.

Here is the code,

public static void getUser(Handler.Callback callback){
    DatabaseHelper.userDB.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            User userObj = dataSnapshot.getValue(User.class);;

            Message message = new Message();
            Bundle bundle = new Bundle();
            bundle.putSerializable("user",userObj); //Make sure that user object is serialisable
            message.setData(bundle);
            callback(message);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Message message = new Message();
            Bundle bundle = new Bundle();
            bundle.putSerializable("user",null);
            message.setData(bundle);
            callback(message);
        }
    });

}

Here is how you should call this function:

getUser(new Handler.Callback(){
        @Override
        public boolean handleMessage(Message message) {
            if(message != null){
               User user = (User)message.getData().get("user");
               //Do whatever you want with "user" object
            }
            return false;
        }
    });

This will make your code modular. You can call this function anywhere in your code to get user object and you can keep all your firebase database listener code in a single place for separation of database layer and logic layer.

Upvotes: 0

Salman500
Salman500

Reputation: 1211

user[0] will always be null because firebase database is asynchronous

// in userdb it should be like this
// database.child("users").child("uid")
private User mUser = null;
public void getUser(){

    DatabaseHelper.userDB.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
              if dataSnapshot.exists(){
                 mUser = dataSnapshot.getValue(User.class);
           // do something with user
                      }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

Upvotes: 1

Nirel
Nirel

Reputation: 1925

Firebase database is async,

When the code gets into the 'return' line, the block of code in the 'onDataChange' callback didn't executed

Please, read that article to learn more about async and sync methods

Upvotes: 1

Related Questions