Firebase实时数据库单值监听器多次触发

Posted

技术标签:

【中文标题】Firebase实时数据库单值监听器多次触发【英文标题】:Firebase Realtime database single value listener triggering many times 【发布时间】:2018-08-02 15:37:13 【问题描述】:

我正在尝试从其他值侦听器中的数据库接收数据。

类 MyFragment : Fragment()

private lateinit var reference: DatabaseReference

override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    reference = FirebaseDatabase.getInstance().reference.child("FIRST_ROOT")
            .child("FIRST_CHILD")
            .child("CHILD_1")


override fun onActivityCreated(savedInstanceState: Bundle?) 
    super.onActivityCreated(savedInstanceState)
    reference.addValueEventListener(object : EventListener() 
        override fun onDataChange(p0: DataSnapshot?) 
            val childOfSecondRoot= p0?.value
            FirebaseDatabase.getInstance().reference.child("SECOND_ROOT")
                      .child(childOfSecondRoot).addListenerForSingleValueEvent(object : EventListener() 
                          override fun onDataChange(p0: DataSnapshot?) 
                             doingMyJob(p0?.value)
                    
            )
        
    )

我的目标是每次参考观察值的变化运行一次方法doingMyJob

由于某种原因,添加为addListenerForSingleValueEvent 的事件侦听器在每次reference 触发器时再调用一次方法doMyJob,而不是每次更改只运行一次。第一次从reference 读取是可以的,但是第二次调用doMyJob 2 次,第三次调用 3 次,依此类推。重启后应用历史从头开始。方法doMyJob() 不会更改数据库中的任何值。

现在我知道,对于观察值的每一次变化,都会递增地调用父侦听器。

数据库结构:

|MAIN_ROOT |\FIRST_ROOT | \FIRST_CHILD | |DATA_TO_RECEIVED //reference field - parent listener for many events |\SECOND_ROOT | \DATA_TO_RECEIVED // root name received in nested listener-as single value | |CHILD_1 | |CHILD_2 | |CHILD_3

我做错了吗?是否有可能从侦听器运行侦听器以避免嵌套侦听器的增量调用?

PS:抱歉代码很丑。我试图尽可能地简化问题。

【问题讨论】:

doingMyJob 到底是做什么的? @DougStevenson 它显示了对话框,但我认为这没有任何意义。 也许您可以更新您的问题以准确解释您在此处尝试完成的工作,以及代码中的一些日志行,以及帮助我​​们了解实际情况的日志输出. @Doug Stevenson 我添加了数据库结构 【参考方案1】:

您在第二个查询中使用singleEventListener,但在您的第一个查询中,您仍在使用不会自动消失的普通事件侦听器。所以这可能是你的代码被多次调用的原因。所以问题不在于你的 single event listener 被多次调用,而是上面的那个可能是并且每次它创建一个新的 single event listener 反过来多次调用你的方法。

reference.addValueEventListener(object : EventListener()  //ordinary event listener will be kept running 
        override fun onDataChange(p0: DataSnapshot?) 
            val childOfSecondRoot= p0?.value
            FirebaseDatabase.getInstance().reference.child("SECOND_ROOT")
                      .child(childOfSecondRoot).addListenerForSingleValueEvent(object : EventListener() 
                          override fun onDataChange(p0: DataSnapshot?) 
                             doingMyJob(p0?.value)
                    
            )
        
    )

【讨论】:

你是对的。父侦听器多次触发。不幸的是,这仍然不能解决我的问题。每次更改观察值后,父侦听器每次更改都会增量调用一次。这种方式应该有效吗? 另外,您是否尝试过为单个事件替换第一个侦听器?还是需要它来持续监控节点? 我需要它乘以,因为第一次调用返回 null。 您的第二个监听器是否更改了第一个监听器引用中的数据?这可能会导致您看到的增量效果:/ 不。 doMyJob 在开始做任何事情之前被多次调用。【参考方案2】:

有趣的事情。方法 doMyJob 在显示对话框启动新片段后(抱歉在我的问题中错过了它)并且在我关闭它之后重新启动在 onActivityCreated 中添加侦听器的片段,所以... val reference 再次分配并添加了另一个侦听器。

我就是喜欢这种虫子。谢谢大家的帮助。

【讨论】:

以上是关于Firebase实时数据库单值监听器多次触发的主要内容,如果未能解决你的问题,请参考以下文章

如何实现一个 Firebase 监听器来观察数据库的实时变化

使用云功能在 Firebase 实时数据库中交换排名 - 游戏

我们可以在 ios serviceworker 上运行 firebase 实时监听吗?

Firebase 实时数据库:如何监听节点的特定项目子集?

input事件中文触发多次问题研究

在 Firebase 函数中为实时数据库使用 onWrite 触发器