首页 > 解决方案 > 如何根据 Firebase 实时数据库中的“设备”子项在 RecyclerView 中显示数据“用户设备”设备名称

问题描述

这是我的示例 Firebase 实时数据库

{
  "devices": {
    "123456": {
      "device_mac_id": "123456",
      "device_name": "BOX 12",
      "id": "2"
    },
    "222222": {
      "device_mac_id": "222222",
      "device_name": "BOX 22",
      "id": "3"
    },
    "888888": {
      "device_mac_id": "888888",
      "device_name": "BOX 88",
      "id": "6"
    }
  },
  "users": {
    "UcI1REoXAoSC7mg4u7RGbw8gR2g2": {
      "email_id": "ab@cd.com",
      "full_name": "Ab Cd",
      "id": "UcI1REoXAoSC7mg4u7RGbw8gR2g2",
      "user_devices": {
        "-MIbRGtT25ki36foJ6b5": "888888",
        "-MIc-ORsWRqO45OJrBXg": "123456"
      }
    }
  }
}

仪表板片段.java

{
    showProgressBar();

    deviceModelArrayList.clear();
    devicesAdapter.notifyDataSetChanged();

    mDatabaseRef
            .child("users")
            .child(FirebaseAuth.getInstance().getUid())
            .child("user_devices")
            .orderByKey()
            .addChildEventListener(
                    new ChildEventListener() {
                        @Override
                        public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                            Log.e(TAG,
                                    "onChildAdded:"
                                            + " snapshot:" + snapshot.getValue()
                                            + " previousChildName:" + previousChildName);
                            getDeviceData(snapshot.getValue(String.class));
                        }

                        @Override
                        public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                            Log.e(TAG,
                                    "onChildChanged:"
                                            + " snapshot:" + snapshot.getValue()
                                            + " previousChildName:" + previousChildName);
                        }

                        @Override
                        public void onChildRemoved(@NonNull DataSnapshot snapshot) {
                            Log.e(TAG,
                                    "onChildRemoved:"
                                            + " snapshot:" + snapshot.getValue());
                        }

                        @Override
                        public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                            Log.e(TAG,
                                    "onChildMoved:"
                                            + " snapshot:" + snapshot.getValue()
                                            + " previousChildName:" + previousChildName);
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError error) {
                            Log.e(TAG,
                                    "onCancelled:"
                                            + " error:" + error.toString());
                        }
                    });
}


private void getDeviceData(String deviceID) {
    if (deviceID != null) {
        mDatabaseRef
                .child("devices")
                .child(deviceID)
                .addListenerForSingleValueEvent(
                        new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                hideProgressBar();

                                // This method is called once with the initial value and again
                                // whenever data at this location is updated.
                                UserModel.DeviceModel deviceModel = dataSnapshot.getValue(UserModel.DeviceModel.class);
                                Log.e(TAG, "onDataChange: devices: " + deviceModel.getDevice_name());

                                deviceModelArrayList.add(deviceModel);
                                devicesAdapter.notifyDataSetChanged();
                            }

                            @Override
                            public void onCancelled(DatabaseError error) {
                                hideProgressBar();
                                // Failed to read value
                                Log.w(TAG, "Failed to read value.", error.toException());
                            }
                        }
                );
    }
}

我想在 RecyclerView 中显示,但数据随着 onDataChanged 不断增加,我正在将对象添加到 ArrayList。如果我错了或最佳实践,请建议我。

标签: androidfirebaseandroid-studiofirebase-realtime-databasefirebaseui

解决方案


根据您的最后评论:

是的,有 3 台设备,但我只为用户分配了 2 台。

要获取DeviceModel仅与特定用户对应的对象,您需要使用该方法两次遍历 DataSnapshot 对象getChildren(),如以下代码行所示:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userDevicesRef = rootRef.child("users").child(uid).child("user_devices");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot userDeviceSnapshot : dataSnapshot.getChildren()) {
            String deviceId = userDeviceSnapshot.getValue(String.class);
            DatabaseReference userDevicesRef = rootRef.child("devices").child(deviceId);
            ValueEventListener eventListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot deviceSnapshot) {
                    UserModel.DeviceModel deviceModel = dataSnapshot.getValue(UserModel.DeviceModel.class);
                    Log.d("TAG", deviceModel.getDevice_name());
                }

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

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

logcat 中的结果将是:

BOX 88
BOX 12

但这只是为了看到它正在起作用。在您的情况下,您应该将这些对象添加到列表中并通知适配器有关更改。


推荐阅读