如何在Firebase数据库不同节点检查当前快照Key是否存在
问题
我希望在addChildEventListener中,检查当前snapshot.getKey()是否存在于同一数据库的另一个路径中。
我的数据库结构如下:
{ "Activity": { "Do": { "-NTW-cLFvmgSqZ72EKuJ": { "name": "kayaking " }, "-NTW-u8LJKsGd-wpcmir": { "name": "climbing " } }, "Users": { "wkFbhmSH6lfPkkyy6OGke0be1ys2": { "gender": "Male", "preferences": { "Do": { "-NTW-cLFvmgSqZ72EKuJ": true} } } } }
我想只在用户未回答过活动喜好时,才生成对应的问题卡片。目前我写了监听活动节点的代码,但不知道如何检查当前活动ID是否已存在于用户的偏好路径中:
DatabaseReference selectedActivityDatabase = FirebaseDatabase.getInstance().getReference().child("Activity").child("Do"); selectedActivityDatabase.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(@NonNull DataSnapshot activitySnapshot, @Nullable String previousChildName) { if (activitySnapshot.exists()){ currentActivityId = activitySnapshot.getKey(); cards item = new cards(activitySnapshot.getKey(),activitySnapshot.child("name").getValue().toString()); rowItems.add(item); String key = activitySnapshot.getKey(); activityTpeArrayAdapter.notifyDataSetChanged(); } } // 其他未实现的ChildEventListener方法省略 });
我需要检查activitySnapshot.getKey()是否存在于users/{userId}/preferences/Do路径下,但不清楚如何将活动ID传入用户节点的监听器中,试过全局变量和独立函数都没成功。
解决方案
你可以直接在onChildAdded方法内部针对当前活动ID查询用户偏好节点,利用Java闭包特性直接访问外部变量,不需要全局变量传递参数,具体实现如下:
- 先获取当前登录用户ID
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
- 在活动监听器内嵌套查询用户偏好
DatabaseReference selectedActivityDatabase = FirebaseDatabase.getInstance().getReference().child("Activity").child("Do"); selectedActivityDatabase.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(@NonNull DataSnapshot activitySnapshot, @Nullable String previousChildName) { if (activitySnapshot.exists()){ String activityId = activitySnapshot.getKey(); String activityName = activitySnapshot.child("name").getValue(String.class); // 构建当前用户该活动偏好的数据库引用 DatabaseReference userPrefRef = FirebaseDatabase.getInstance() .getReference("Users") .child(userId) .child("preferences") .child("Do") .child(activityId); // 一次性查询该节点是否存在(不需要持久化监听) userPrefRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot prefSnapshot) { // 只有用户未评价过该活动时,才生成问题卡片 if (!prefSnapshot.exists()) { cards item = new cards(activityId, activityName); rowItems.add(item); activityTpeArrayAdapter.notifyDataSetChanged(); } } @Override public void onCancelled(@NonNull DatabaseError error) { // 处理查询失败的情况 Log.e("Firebase", "查询用户偏好失败", error.toException()); } }); } } // 实现ChildEventListener的其他抽象方法 @Override public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {} @Override public void onChildRemoved(@NonNull DataSnapshot snapshot) {} @Override public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {} @Override public void onCancelled(@NonNull DatabaseError error) {} });
- 关键说明
- 使用
addListenerForSingleValueEvent做一次性查询,避免不必要的持久化监听,节省资源。 - 内部的
ValueEventListener可以直接访问外部的activityId变量(Java支持访问外部有效final变量),无需额外传递逻辑。 - 只要用户偏好节点存在(无论值是true还是false),都判定为已回答过,跳过卡片生成;仅当节点不存在时才生成。
内容的提问来源于stack exchange,提问作者Seán Cahill
相关产品推荐
相关产品推荐

