【问题标题】:What is the difference between get() and addListenerForSingleValueEvent?get() 和 addListenerForSingleValueEvent 有什么区别?
【发布时间】:2021-05-10 08:06:50
【问题描述】:

我看到很多关于在 Android 上使用 Firebase 实时数据库的教程、文档和问题都在谈论 addListenerForSingleValueEvent 方法。这个方法从数据库中读取一次值,就是我想做的。

但是在我的 IDE 和文档中的自动完成中,我还看到了一个名为 get() 的方法,它似乎也从数据库中读取了一次值。从名称和签名来看,它似乎更简单、更现代(因为它返回一个Task)。但由于提到的其他方法太多了,我想确保我使用的是正确的代码。

那么get()addListenerForSingleValueEvent 之间有什么区别,为什么后者在文档、教程和问题中提到的更多,当我想从数据库中读取一次值时应该使用哪一个?

【问题讨论】:

    标签: java android firebase kotlin firebase-realtime-database


    【解决方案1】:

    首先:请记住,Firebase 实时数据库最适合用于通过使用长寿命侦听器在客户端和数据库服务器(或多个客户端之间)之间保持数据同步。在 Android 上,您可以使用 addValueEventListener 执行此操作,您应该尽可能尝试使用它。

    但在某些情况下,您可能只想从数据库中读取一次值。所以让我们看看我是否可以依次回答问题,从最重要的问题开始:

    当我想从数据库中读取一次值时应该使用哪种方法?

    如果您只需要从数据库中读取一次值,请使用新的get() 方法。

    在 Java 中看起来像这样:

    ref.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DataSnapshot> task) {
            if (!task.isSuccessful()) {
                Log.e("firebase", "Error getting data", task.getException());
            }
            else {
                Log.d("firebase", String.valueOf(task.getResult().getValue()));
            }
        }
    });
    

    在 Kotlin 中是:

    ref.get().addOnSuccessListener {
        Log.i("firebase", "Got value ${it.value}")
    }.addOnFailureListener{
        Log.e("firebase", "Error getting data", it)
    }
    

    addListenerForSingleValueEvent 被提及的次数太多了,为什么你推荐使用get()

    我们在我们的第一个 Android SDK 中引入了addListenerForSingleValueEvent,从那时起它就一直存在。多年来,我们编写了很多教程,提出了很多问题并得到了解答。

    我们当然会更新文档。但是我们无法更新所有教程。所以在可预见的未来,提到addListenerForSingleValueEvent 的次数将超过新的get() 方法。

    get()addListenerForSingleValueEvent 有什么区别?

    如前所述:addListenerForSingleValueEvent 方法只要存在就一直是 Firebase Android SDK 的一部分,用于从数据库中读取一次值。它通过以下方式做到这一点:

    1. 使用addValueEventListener 附加侦听器
    2. 等待值从持久层显示
    3. 致电onDataChange
    4. 删除监听器

    这非常有效......直到我们在 SDK 2.0 版中引入了磁盘缓存(早在 2015 年 I/O 大会上)。在此之前,步骤 2 中的所有值将始终来自服务器,因为客户端已经有一个侦听器,或者因为这会将第一个侦听器附加到服务器。但是对于磁盘缓存,如果您之前读取了该值但当前没有侦听器,则第 2 步将从磁盘缓存中读取该值,并且您的 onDataChange 将立即使用该值调用。即使服务器上的值已经更新。事实上,监听器会在后台更新磁盘缓存中的值,但只有在使用缓存中的(可能是陈旧的)值调用您的onDataChange 之后。

    虽然可以解释这种行为,但这并不是几乎所有人想要的。不幸的是,我们发现这种边缘情况为时已晚,无法将其归类为简单的实现错误并进行修复。所以我们把它留在里面,并建议人们要么使用磁盘持久性使用addListenerToSingleValueEvent,但不能同时使用。或者,您可以在同一参考/查询中调用 keepSynced(true) 作为解决方法。都很乱,而且不好。

    快进 5 年多,我们终于推出了一种不再有这种尴尬行为的新方法。由于自 2015 年以来 Android API 发生了很大变化,我们还使用了(稍微)更现代的方法签名:Task&lt;DataSnapshot&gt; get()

    【讨论】:

    • 太棒了!对我来说,这也使代码更清晰、更易于理解。
    • 并且由于它使用 Tasks API,它: 1. 与其他 Firebase API 更加一致; 2. 让 Kotlin Coroutines 更易于使用(您可以简单地使用 kotlinx-coroutines-play-services library
    • 感谢@RosárioPereiraFernandes 的澄清。这就是我在上一期“更现代”的意思,但你的例子在优势方面更加具体。
    猜你喜欢
    • 1970-01-01
    • 2014-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 2011-02-01
    • 2015-08-03
    相关资源
    最近更新 更多