从数据库中的特定用户标识子节点读取值

时间:2018-03-19 22:45:36

标签: java android firebase firebase-realtime-database

我知道这已被问过100次,但似乎没有一个解决方案适合我。

想要阅读" user_preferences"的数据库对于已登录的用户(userID)并读取性别/年龄/体重/身高值并将其存储在下面显示的变量中。当前在所有内容(日志语句和值)上返回null。感觉我没有正确设置路径或其他东西。帮助会很棒!

db

和我的代码

       mAuth = FirebaseAuth.getInstance();
        mFirebaseDatabase = FirebaseDatabase.getInstance();
        myRef = mFirebaseDatabase.getReference();
        userID = mAuth.getCurrentUser().getUid();
        DatabaseReference testRef = myRef.child("user_preferences");


        testRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {


                        for (DataSnapshot ds : dataSnapshot.getChildren()) { //loop through the firebase nodes

                            UserPreferences userPreferences = new UserPreferences();


                            userPreferences.setAge(ds.child(userID).getValue(UserPreferences.class).getAge()); 
                            userPreferences.setHeight(ds.child(userID).getValue(UserPreferences.class).getHeight()); 
                            userPreferences.setWeight(ds.child(userID).getValue(UserPreferences.class).getWeight()); 
                            userPreferences.setGender(ds.child(userID).getValue(UserPreferences.class).getGender());

                            genderSet = userPreferences.getGender();
                            age = userPreferences.getAge();
                            height = userPreferences.getHeight();
                            weight = userPreferences.getWeight();

                            Log.d(TAG, "onDataChange: " + genderSet);
//
                        }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });


    }

2 个答案:

答案 0 :(得分:2)

这两行代码:

DatabaseReference testRef = myRef.child("user_preferences");
testRef.addValueEventListener(...)

有效地查询名为user_preferences整个节点。这意味着该位置的所有内容 - 所有用户。听起来这不是你想要的。如果您只想查询单个用户,则应通过向查询位置添加所需的用户ID来明确查询该用户:

DatabaseReference testRef = myRef.child("user_preferences").child(userID);
testRef.addValueEventListener(...)

此外,这些代码行让我感到困惑:

userPreferences.setAge(ds.child(userID).getValue(UserPreferences.class).getAge()); 
userPreferences.setHeight(ds.child(userID).getValue(UserPreferences.class).getHeight()); 
userPreferences.setWeight(ds.child(userID).getValue(UserPreferences.class).getWeight()); 
userPreferences.setGender(ds.child(userID).getValue(UserPreferences.class).getGender());

您要为要填充的每个字段反序列化UserPreferences对象,这很浪费。在我看来,你真的只想反序列化一次并记住对象:

UserPreferences userPreferences = dataSnapshot.getValue(UserPreferences.class);

答案 1 :(得分:1)

关于空值,您似乎正在使用外部字段,在Firebase至少在一秒钟后返回网络调用之前,不会设置外部字段。在此期间,您的值将为null,因此您不应将它们设置为onDataChange之外的UI元素。

此外,当你只需要为该类调用一个getValue(),然后为字段调用另外一个时,你会有很多获取/设置。

然后,您似乎不想循环任何内容,因此您应该从顶部引用直接访问用户节点。

例如,

    mAuth = FirebaseAuth.getInstance();
    mFirebaseDatabase = FirebaseDatabase.getInstance();
    myRef = mFirebaseDatabase.getReference();
    userID = mAuth.getCurrentUser().getUid();
    DatabaseReference testRef = myRef.child("user_preferences/"+userID);
    // or .child("user_preferences").child(userID)


    testRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            UserPreferences userPreferences = dataSnapshot.getValue(UserPreferences.class);
            Log.d(TAG, "onDataChange: " + userPreferences.getGender());

            // TODO: Update some UI element here
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            // TODO: Add error handling
        }
    });

}

如果您只想阅读一次值,请使用testRef.addListenerForSingleValueEvent()