Maarten Weyns
Maarten Weyns

Reputation: 455

getKey() returns value instead of ID

I'm trying to get the ID of a specific child in a Firebase Database. The database looks like this:

Users:

 - id: user1
 - id: user2
 - ...

Now I want to return ID of each user and I tried it with this;

DatabaseReference databaseRef = FirebaseDatabase.getInstance().getReference();
        ValueEventListener users = databaseRef.child("Users").child(bundle.getString("User")).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                String userID = dataSnapshot.getKey();


                mTextView.setText(userID);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                //error
            }
        });

bundle.getString("User") is the String that contains the value of which user I want to get the ID from.

When I open the app, the text in mTextView just contains the username instead of the ID.

What did I do wrong here?

The app is a ListView in the main activity containing all the users. When the user clicks on a list item a new activity opens. In this activity I want to show the selected user's info but for that i want to get the ID to find the corresponding info in the database with the same ID..

JSON:

{
  "Users" : [ null, "Jef", "Peter", "Jean", "Ronny" ]
}

Upvotes: 1

Views: 226

Answers (1)

Wilik
Wilik

Reputation: 7720

It is recommended for you to read this article Best Practices: Arrays in Firebase

arrays are quite handy. But for distributed data, they aren't reliable because they lack a unique, permanent way to access each record.

It means you can't retrieve each index of the array under Users. You can retrieve the whole array first (databaseRef.child("Users").addValueEventListener()), cast the returned dataSnapshot to an array and then check the value manually or use contains method.

What I suggest is to change your database structure to like this

{
    "Users" : {
        "Jef" : true,
        "Peter" : true,
        "Jean" : true,
        "Ronny" : true
    }
}

With this database structure, you don't need to change the code because it should work already.

EDIT: For your case, you can save the other user details in the other node of the database

{
    "Users" : {
        "Jef" : true,
        "Peter" : true,
        "Jean" : true,
        "Ronny" : true
    },
    "Users_details" : {
        "Jef" : {
            "city" : "some_city_name",
            "address" : "some_address_name",
            "phone_number" : "some_phone_number"
        },
        "Peter" : {
            "city" : "some_city_name",
            "address" : "some_address_name",
            "phone_number" : "some_phone_number"
        },
        "Jean" : {
            ...
        },
        ...
    }
}
  • To get the list of usernames, you just need to listen to Users node
  • Then, when a view in the listview is clicked, send the username as intent extra to the other activity intent.putExtra("username", username);
  • Finally, in the new activity, listen to Users_details/<username_from_intent> to get the user details (phone number, address, etc)

Hope this helps, this structure is definitely better than saving each detail in an array. If you read the first link I provided, this practice should be avoided because you might change the user details.

Upvotes: 2

Related Questions