如何根据 Firebase 实时数据库中的“设备”子项在 RecyclerView 中显示数据“用户设备”设备名称
Posted
技术标签:
【中文标题】如何根据 Firebase 实时数据库中的“设备”子项在 RecyclerView 中显示数据“用户设备”设备名称【英文标题】:How to show data "user_devices" device_name in RecyclerView based on "devices" child from Firebase Realtime Database 【发布时间】:2021-01-21 04:52:43 【问题描述】:这是我的 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"
DashboardFragment.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 添加对象。如果我错了或最佳做法,请建议我。
【问题讨论】:
为了更好理解,需要从users->uid->user_devices
获取用户设备,其实是两个,888888和123456,根据这些值,需要获取@中存在的设备对象987654324@,对吧?
@Alex 是的,有 3 台设备,但我只为用户分配了 2 台。
【参考方案1】:
根据你上一条评论:
是的,有 3 台设备,但我只为用户分配了 2 台。
要获取只对应特定用户的DeviceModel
对象,需要使用getChildren()
方法循环DataSnapshot对象两次,如下代码行所示:
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
但这只是为了看到它正在工作。在您的情况下,您应该将这些对象添加到列表中并通知适配器有关更改。
【讨论】:
谢谢伙计。您的回答很周到,但我的挑战是处理列表。我找到了解决方案并在这里回答。【参考方案2】:感谢@Alex 及时回复。
在等待答案的同时,我对FirebaseUI for Realtime Database做了一些研究
dependencies
// FirebaseUI for Firebase Realtime Database
implementation 'com.firebaseui:firebase-ui-database:x.y.z'
我对 FirebaseRecyclerAdapter 感觉更舒服,因为我的挑战是处理列表。
这是我的代码 sn-ps 对我有用。
firebaseRecyclerOptions =
new FirebaseRecyclerOptions
.Builder<String>()
.setQuery(mDatabaseRef.child("users").child(mFirebaseAuth.getUid()).child("user_devices"), String.class)
.build();
firebaseRecyclerAdapter =
new FirebaseRecyclerAdapter<String, DevicesViewHolder>(firebaseRecyclerOptions)
@Override
protected void onBindViewHolder(@NonNull DevicesViewHolder holder, int position, @NonNull 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
UserModel.DeviceModel deviceModel = dataSnapshot.getValue(UserModel.DeviceModel.class);
Log.e(TAG, "onDataChange: devices: " + deviceModel.getDevice_name());
holder.b.btnPowerBox.setText(deviceModel.getDevice_name());
@Override
public void onCancelled(DatabaseError error)
hideProgressBar();
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
);
holder.b.btnPowerBox.setOnClickListener(view ->
Log.d(TAG, "onBindViewHolder: Button clicked at position " + position);
);
@NonNull
@Override
public DevicesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
ItemDevicesBinding bItem = ItemDevicesBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DevicesViewHolder(bItem);
@Override
public void onDataChanged()
// If there are no chat messages, show a view that invites the user to add an item to list.
b.tvEmptyListMessage.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
;
firebaseRecyclerAdapter.startListening();
b.rvDevices.setAdapter(firebaseRecyclerAdapter);
【讨论】:
以上是关于如何根据 Firebase 实时数据库中的“设备”子项在 RecyclerView 中显示数据“用户设备”设备名称的主要内容,如果未能解决你的问题,请参考以下文章
如何根据 Firebase 分析中的总收入分析设备和操作系统分布?
如何实现一个 Firebase 监听器来观察数据库的实时变化
如何根据 Firebase 数据库中的条目向我的 android 应用发送通知? [关闭]