get() 和 addListenerForSingleValueEvent 之间有什么区别?

时间:2021-02-06 00:41:12

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

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

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

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

1 个答案:

答案 0 :(得分:5)

首先:请记住,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)
}

get() 被提及得更多时,您为什么建议使用 addListenerForSingleValueEvent

我们在第一个 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 年多,我们终于推出了一种新方法,不再有这种尴尬的行为。由于 Android API 自 2015 年以来发生了很大变化,我们还使用了(稍微)更现代的方法签名:Task<DataSnapshot> get()

相关问题