0

I am trying to read a list of data from a user account which looks like this: db

But the onDataChange listener is not being called.

I would like to get the values of "checked" and "desc"; However, when I add a listenForSingleValueEvent listener like below, onDataChange is not called and I do not retrieve the values.

DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("accounts")
            .child(uid).child("user_t").child(item_id);
//"user_t" has been shortened for this post

    databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Log.i(TAG, "onDataChange: Getting single data");

            String name = (String) dataSnapshot.child("checked").getValue();
            String date = (String) dataSnapshot.child("desc").getValue();
        }
    //on Cancel etc..
    };

Even with only:

String name = (String) dataSnapshot.child("checked").getValue();"

Inside onDataChange it still will not fire. From what I've read from the Firebase docs, I must use a listener to read data.

I have similar code in another section of the app which more or less does the same thing as the above code is supposed to and it works perfectly.

I've been having a lot of trouble with Firebase recently so any help appreciated. Cheers!

EDIT: Some more code with the same result:

DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("accounts").child(uid);
databaseReference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Log.i(TAG, "onDataChange: ");
        String name = dataSnapshot.child("name").getValue().toString();
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

EDIT 2: I am able to create a key and set a value to it, in the account section and the item section, but it will call the onDataChange function. I have been able to bypass this issue; however, the listener is then called once its calling class has been deconstructed and a NullPointerException is thrown because the class level variables no longer exist.

EDIT 3 - Entire class:

This is a different class but I am having the exact same problem with it.

public class StartActivity extends AppCompatActivity {

//firebase variables
private FirebaseAuth mAuth;
private FirebaseUser currentUser;
private FirebaseDatabase database;
private DatabaseReference userReference;
private String uid;
private String accountType;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    //set splash theme
    setTheme(R.style.SplashStyle);
    super.onCreate(savedInstanceState);

    //get an authentication instance
    mAuth = FirebaseAuth.getInstance();
    //get user database
    database = FirebaseDatabase.getInstance();
    userReference = database.getReference(ACCOUNTS);


    //get the user and check if logged in
    currentUser = mAuth.getCurrentUser();
    if (currentUser != null){
        uid = currentUser.getUid();
        getAccountType();

        //open the dashboard
        openDashboard();
    }else{
        openLogin();
    }

    finish();
}

private void openDashboard() {
    Intent dashboard = new Intent(this,Dashboard.class);

    dashboard.putExtra(String_Values.ACCOUNT_TYPE,accountType);
    dashboard.putExtra(String_Values.ACCOUNT_UID,uid);

    startActivity(dashboard);
    finish();

}

private void openLogin(){
    Intent loginIntent = new Intent(this,Login.class);
    startActivity(loginIntent);
}


private void getAccountType(){
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference databaseReference = database.getReference(ACCOUNTS).child(uid);
    Log.i(String_Values.TAG, "uid: " + uid);
    databaseReference.addListenerForSingleValueEvent(get_account_listener);
}

ValueEventListener get_account_listener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        accountType = dataSnapshot.child(TYPE).getValue().toString();
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.i(String_Values.TAG, "onCancelled: " + databaseError.getMessage());
    }
};

}
Liam G
  • 771
  • 2
  • 9
  • 26

2 Answers2

2

You cannot get anything because you aren't looping to get the children within the DataSnapshot object. So to solve this, please use the following lines of code:

DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("accounts")
        .child(uid).child("user_t");
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String name = ds.child("checked").getValue(String.class);
            String date = ds.child("desc").getValue(String.class);
        }

    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
    }
};

If you it still doesn't fire, please check the logcat to see that databaseError.getMessage() returns.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • What happens if you hardcode the values in your reference (`uid`, `user_t` and so n), does it work? – Alex Mamo Jan 12 '19 at 11:08
  • Yeah same thing happening when I hard code the values. I can actually create and set values in that persons account, but just can't read anything from it? – Liam G Jan 13 '19 at 04:04
  • Did you do dome changes to your database structure? Can you please share the code for your entire class? – Alex Mamo Jan 13 '19 at 08:38
  • No changes to the structure, but I can add a key and value to exactly the location I want to retrieve values. I've added a class I am having the problem with. – Liam G Jan 13 '19 at 10:42
  • Under `accounts` node there should be the `uid`, right? But I see in your code something related to `test`. How is this possible? Can you please share the real database structure? – Alex Mamo Jan 13 '19 at 15:28
  • In that above data structure, "test" is just a hard coded UID, I made sure to hard code that in my tests. I have created another account for my app and have been using that in my latest tests, so as to ensure that the right UID is pulled from `Firebase Auth` and used in the database. – Liam G Jan 14 '19 at 01:32
  • I misunderstood some basic Firebase concepts in regards to Asynchronous callbacks. Alex, your answer [here](https://stackoverflow.com/a/47853774/6634934), is perfect! – Liam G Jan 14 '19 at 02:56
0

Thanks to Alex Mamo for his answer here. Perfectly explained.

Liam G
  • 771
  • 2
  • 9
  • 26