从Firebase检索复杂的嵌套数据

时间:2019-08-22 21:12:42

标签: android firebase-realtime-database

我在firebase中有如下数据: Firebase screenshot

我想获取每个表单ID的客户和设备详细信息。表单ID由firebase唯一生成。 我只是需要以某种方式访问​​这些表单ID。

我将databaseReference设置如下:

databaseReference = FirebaseDatabase.getInstance().getReference("users").child(userID).child("forms");

然后我尝试了以下代码来检索所需的数据:

databaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot formsSnapshot : dataSnapshot.getChildren()) {
                    for (DataSnapshot formIDSnapshot : formsSnapshot.getChildren()) {

                        Device device = formIDSnapshot.getValue(Device.class);
                        if (device != null) {
                            // get and use the data
                        }
                    }
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

更新: 由于@Frank的回答,我现在能够成功检索表单ID。 现在,要获取设备和客户详细信息,我必须在获取表单ID之后在ValueEventListener中编写以下代码:

databaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot formsSnapshot : dataSnapshot.getChildren()) {
                    String formID = formsSnapshot.getKey();    //Retrieving the formID here

            //New code addition
            // to get the reference to device details node
                    databaseReference.child(Objects.requireNonNull(formID)).child("Device details").addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            Device device = dataSnapshot.getValue(Device.class);
                            if (device != null) {
                                // required device details here
                            }
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {
                            throw databaseError.toException();
                        }
                    });

            // to get the reference to customer details node
              databaseReference.child(Objects.requireNonNull(formID)).child("Customer details").addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            Customer customer = dataSnapshot.getValue(Customer.class);
                            if (customer != null) {
                                //required customer details here
                            }
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {
                            throw databaseError.toException();
                        }
                    });
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                throw databaseError.toException();
            }
        });

我了解这是一个凌乱的代码,我希望对此使用更简洁的方法。

2 个答案:

答案 0 :(得分:2)

不需要嵌套循环。只需获取子级列表并循环遍历一次即可。在每次迭代时,将dataSnapshot转换为FormID类,然后再使用其属性即可。 如果您不需要一直观察数据,我还建议您使用SingleValueEventListener而不是ValueEventListener

答案 1 :(得分:2)

您可以通过调用DataSnapshot.getKey()来获取节点的密钥。因此,要获取您的表单ID:

databaseReference = FirebaseDatabase.getInstance().getReference("users").child(userID).child("forms");

databaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot formsSnapshot : dataSnapshot.getChildren()) {
                String formID = formsSnapshot.getKey();
                Device device = formsSnapshot.getValue(Device.class);
                if (device != null) {
                    // get and use the data
                }
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            throw databaseError.toException(); // never ignore errors
        }
    });