You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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闭包特性直接访问外部变量,不需要全局变量传递参数,具体实现如下:

  1. 先获取当前登录用户ID
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
  1. 在活动监听器内嵌套查询用户偏好
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) {}
});
  1. 关键说明
  • 使用addListenerForSingleValueEvent做一次性查询,避免不必要的持久化监听,节省资源。
  • 内部的ValueEventListener可以直接访问外部的activityId变量(Java支持访问外部有效final变量),无需额外传递逻辑。
  • 只要用户偏好节点存在(无论值是true还是false),都判定为已回答过,跳过卡片生成;仅当节点不存在时才生成。

内容的提问来源于stack exchange,提问作者Seán Cahill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 15:22:37