【问题标题】:Firebase android count children and store it in a variableFirebase android 计算子节点并将其存储在变量中
【发布时间】:2020-06-23 03:18:37
【问题描述】:

在我的应用程序中,我可以通过 datasnapshot.getchildren() 计算儿童数量。 但是,如果我想将该计数存储在变量中该怎么办?

mRefReg.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Log.i(dataSnapshot.getKey(),dataSnapshot.getChildrenCount()+"Count");

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

包括“mCount = dataSnapshot.getChildren”似乎不起作用。

【问题讨论】:

  • 为什么“mCount =...”不起作用?如果 mCount 是在匿名类之外定义的变量,它应该可以工作。您的身份的错误信息是什么?
  • Firebase 最近发布了 Cloud Functions。看看这个answer了解更多详情

标签: android firebase count firebase-realtime-database


【解决方案1】:

您看到的可能是 Firebase 中的数据是异步加载的。当你第一次遇到这种情况时,这是一个巨大的范式转变。但由于大多数现代云 API 都以这种方式工作,因此最好尽快接受它。

我发现的最简单的方法是查看当我们放置一些日志语句时会发生什么:

System.out.println("Before adding listener");
mRefReg.addValueEventListener(new ValueEventListener() {
    public void onDataChange(DataSnapshot dataSnapshot) {
        System.out.println("In onDataChange");
    }
    public void onCancelled(DatabaseError databaseError) { }
});
System.out.println("After adding listener");

与你的直觉告诉你的相反,它的输出将是:

添加监听器之前

添加监听器后

在 onDataChange 中

原因是(正如我在开始时所说)Firebase 异步从数据库中获取数据。一种有趣的方式来了解为什么会这样,是对您的数据进行更改(例如在您的Firebase Database console 中)。当您进行此更改时,onDataChange 将再次被调用并打印另一个:

在 onDataChange 中

很遗憾,这意味着您无法执行以下操作来处理孩子数:

int count = -1;
System.out.println("Before adding listener, count="+count);
mRefReg.addValueEventListener(new ValueEventListener() {
    public void onDataChange(DataSnapshot dataSnapshot) {
        count = dataSnapshot.getChildrenCount();
        System.out.println("In onDataChange, count="+count);
    }
    public void onCancelled(DatabaseError databaseError) { }
});
System.out.println("After adding listener, count="+count);

因为输出将是:

添加监听器之前:count=-1

添加监听器后:count=-1

在 onDataChange 中:count=3(假设您有 3 个孩子)

我发现处理这种异步加载的最佳技巧是重新构建问题。不要说“首先我们得到计数,然后我们用它做 xyz”,而是尝试将其构建为“每当我们得到计数时,就用它做 xyz”。这意味着你需要将需要计数的代码移动到 onDataChange():

mRefReg.addValueEventListener(new ValueEventListener() {
    public void onDataChange(DataSnapshot dataSnapshot) {
        int count = dataSnapshot.getChildrenCount();
        // TODO: show the count in the UI
    }
    public void onCancelled(DatabaseError databaseError) { }
});

如果你像这样实现它,UI中的计数将在数据库中的项目数发生变化时更新。

【讨论】:

  • 你确定有没有getNumChildren()这样的方法?因为它给了我错误:“无法解析方法 getNumChildren()”!
  • 无论如何我有另一种方法工作。我只是在整数上使用了“long count = dataSnapshot.getChildrenCount()”,它起作用了!
  • 感谢您指出错误的方法名称。我修复了答案中的代码。
  • 是的,感谢您的帮助。我还有一个疑问,当我的应用程序未通过使用 firebase 离线功能连接到网络时,我如何访问儿童计数?
  • 视情况而定:会自动处理短暂的连接丢失。对于长期缺乏连接,您可以启用磁盘持久性。见firebase.google.com/docs/database/android/offline-capabilities
【解决方案2】:

您的问题中缺少一些信息,但我想我知道发生了什么。 Firebase 中的侦听器是异步的,因此您无法轻松设置变量。

选择:

1) 在 onDataChange 方法中声明你的变量。

2) 仅在 onDataChange 方法完成后使用变量。

3) 在声明监听器的方法中传递一个回调函数。

【讨论】:

    【解决方案3】:
    long ct = 0;    
    
    public void Count() {
                databaseReference.child("a").child("b").addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (dataSnapshot.exists()) {
                            ct = dataSnapshot.getChildrenCount()`enter code here`;
                        } 
                    }
    
                    @Override
                    public void onCancelled(DatabaseError databaseError) {
    
                    }
                });
    
            }
    

    在开始时调用此函数,每当 Firebase 数据库中的子计数增加或减少时,它将不断更新变量 ct。 希望对你有帮助

    【讨论】:

      【解决方案4】:

      只要这样做。 datasnapshot.getChildrenCount 函数返回 long 类型的值,所以你需要先将其转换为整数。

          mRefReg.addValueEventListener(new ValueEventListener() {
                  @Override
                  public void onDataChange(DataSnapshot dataSnapshot) {
                      mCount = (int) dataSnapshot.getChildrenCount;
                      Log.i(dataSnapshot.getKey(), mCount +""`enter code here`);
      
                  }
      
                  @Override
                  public void onCancelled(DatabaseError databaseError) {
      
                  }
              });
      

      【讨论】:

        猜你喜欢
        • 2019-09-30
        • 2021-08-20
        • 2012-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-07
        • 2020-03-16
        • 2011-09-18
        相关资源
        最近更新 更多