如何通过键获取节点列表

时间:2016-08-09 00:56:29

标签: android firebase firebase-realtime-database

我正在开发一个使用firebase的Android应用程序。 该应用程序具有用户,每个用户都有朋友。

users: {
  one: {
    name: Mark,
    friends: {
      two: true,
      three: true
    },
  two: {
    name: Carl
  },
  three: {
    name: Gustav
  }
}

在这个例子中,Mark有两个朋友(Carl和Gustav),另外两个没有朋友。

我想获得马克的朋友名单。

    String userId = "one";
    DatabaseReference friendsDb = db.getReference("users").child(userId).child("friends");
    final DatabaseReference usersDb = db.getReference("users");

    ValueEventListener friendsListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            GenericTypeIndicator<LinkedHashMap<String,Boolean>> t = new GenericTypeIndicator<LinkedHashMap<String,Boolean>>() {};
            LinkedHashMap<String,Boolean> tDataset = dataSnapshot.getValue(t);

            users.clear();
            for( String userId : tDataset.keySet() ) {
                usersDb.child(userId).addListenerForSingleValueEvent(
                        new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                User user = dataSnapshot.getValue(User.class);
                                // how to return the user???
                                // users.add(user);

                            }
                        });
            }

            mAdapter.notifyDataSetChanged();
        }

    };
    friendsDb.addValueEventListener(friendsListener);

我是否使用了关于数据建模和索引的正确方法? 它应该如何回馈我需要的用户列表?

我理解听资源是异步操作,有没有办法一次性获取我需要的值?

任何帮助将不胜感激!谢谢!

修改

Frank van Puffelen提出的解决方案在概念中是正确的,但是没有正确实现。这个概念是调用mAdapter.notifyDataSetChanged();当所有孩子都从firebase db中检索出来时。但它必须检查第一个快照的维度,第二个快照的内容,如下所示。

        DatabaseReference friendsDb = db.getReference("users").child(userId).child("friends");
    final DatabaseReference usersDb = db.getReference("users");

    ValueEventListener friendsListener = new ValueEventListener() {
        @Override
        public void onDataChange(final DataSnapshot dataSnapshot) {
            GenericTypeIndicator<HashMap<String,Boolean>> t = new GenericTypeIndicator<HashMap<String,Boolean>>() {};
            HashMap<String,Boolean> tDataset = dataSnapshot.getValue(t);

            final int usersSize = tDataset.size();

            users.clear();
            for( String userId : tDataset.keySet() ) {
                usersDb.child(userId).addListenerForSingleValueEvent(
                        new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                User user = dataSnapshot.getValue(User.class);
                                users.add(user);
                                if (users.size() == usersSize) {
                                    mAdapter.notifyDataSetChanged();
                                }
                            }
                        });
            }
        }
    };
    friendsDb.orderByKey().addValueEventListener(friendsListener);

2 个答案:

答案 0 :(得分:0)

尝试以这种方式安排数据:

users: {
   one: {
      name: Mark
   },
   two: {
      name: Carl
   },
   three: {
      name: Gustav
   }
},
friends : {
   Mark : {
      two : true, 
      three : true
}
}

答案 1 :(得分:0)

没有Firebase等效的SQL WHERE id IN (1,2,3)。从Firebase pipelines the requests开始,不需要性能。

您的代码看起来很好,除了您没有将用户添加到列表中。我希望您在定义该循环的“退出条件”时遇到问题,即:

ValueEventListener friendsListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        GenericTypeIndicator<LinkedHashMap<String,Boolean>> t = new GenericTypeIndicator<LinkedHashMap<String,Boolean>>() {};
        LinkedHashMap<String,Boolean> tDataset = dataSnapshot.getValue(t);

        users.clear();
        for( String userId : tDataset.keySet() ) {
            usersDb.child(userId).addListenerForSingleValueEvent(
                    new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            User user = dataSnapshot.getValue(User.class);
                            users.add(user);
                            if (users.size() == dataSnapshot.getChildrenCount()) {
                                mAdapter.notifyDataSetChanged();
                            }
                        }
                    });
        }
    }
};