首先:请记住,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 的一部分,用于从数据库中读取一次值。它通过以下方式做到这一点:
- 使用
addValueEventListener 附加侦听器
- 等待值从持久层显示
- 致电
onDataChange
- 删除监听器
这非常有效......直到我们在 SDK 2.0 版中引入了磁盘缓存(早在 2015 年 I/O 大会上)。在此之前,步骤 2 中的所有值将始终来自服务器,因为客户端已经有一个侦听器,或者因为这会将第一个侦听器附加到服务器。但是对于磁盘缓存,如果您之前读取了该值但当前没有侦听器,则第 2 步将从磁盘缓存中读取该值,并且您的 onDataChange 将立即使用该值调用。即使服务器上的值已经更新。事实上,监听器会在后台更新磁盘缓存中的值,但只有在使用缓存中的(可能是陈旧的)值调用您的onDataChange 之后。
虽然可以解释这种行为,但这并不是几乎所有人想要的。不幸的是,我们发现这种边缘情况为时已晚,无法将其归类为简单的实现错误并进行修复。所以我们把它留在里面,并建议人们要么使用磁盘持久性或使用addListenerToSingleValueEvent,但不能同时使用。或者,您可以在同一参考/查询中调用 keepSynced(true) 作为解决方法。都很乱,而且不好。
快进 5 年多,我们终于推出了一种不再有这种尴尬行为的新方法。由于自 2015 年以来 Android API 发生了很大变化,我们还使用了(稍微)更现代的方法签名:Task<DataSnapshot> get()。