get()和addListenerForSingleValueEvent有什么区别? [英] What is the difference between get() and addListenerForSingleValueEvent?

查看:54
本文介绍了get()和addListenerForSingleValueEvent有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到很多关于在Android上使用Firebase实时数据库的教程,文档和问题,它们讨论了 addListenerForSingleValueEvent 方法.这种方法一次要从数据库中读取值,这就是我想要做的.

I see a lot of tutorials, documentation and questions about using the Firebase Realtime Database on Android talk about the addListenerForSingleValueEvent method. This method reads the value from the database once, which is what I want to do.

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

But in the auto-complete in my IDE and in the documentation I also see a method called get(), which also seems to read a value from the database once. From the name and signature it seems simpler, and more modern (as it returns a Task). But since the other method is mentioned so much more, I want to make sure I’m using the right code.

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

So what is the difference between get() and addListenerForSingleValueEvent, why is the latter mentioned so much more in documentation, tutorials and questions, and which one should I use when I want to read a value from the database once?

推荐答案

首先,请记住:Firebase Realtime Database最好用于使客户端与数据库服务器(或多个客户端之间)之间的数据保持同步.使用寿命长的监听器.在Android上,您可以使用 addValueEventListener 进行此操作,您应该尽可能尝试使用它.

First off: keep in mind that Firebase Realtime Database is best when used to keep data in sync between the client and the database server (or between multiple clients) by using a long-lived listener. On Android you do this with addValueEventListener, which you should try to use whenever possible.

但是在某些情况下,您只希望从数据库中读取一次值.因此,让我们看看是否可以从最重要的一个开始依次回答这些问题:

But in some cases you’ll want to read a value from the database only once. So let's see if I can answer the questions in turn, starting with the most important one:

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

If you need to read a value from the database only once, use the new get() method.

在Java中如下所示:

In Java that looks like this:

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 ,此后便一直存在.多年来,已经编写了许多教程,并提出了很多问题.

Why do you recommend using get() when addListenerForSingleValueEvent is mentioned so much more?

We introduced addListenerForSingleValueEvent in our first Android SDK, and it has been there ever since. Over the years a lot of tutorials have been written, and a lot of questions have been asked and answered.

我们正在更新文档.但是,我们无法更新所有教程.因此,在可预见的将来,与新的 get()方法相比,将更多地提及 addListenerForSingleValueEvent .

We’re updating the documentation of course. But there’s no way we can get all tutorials updated. So for the foreseeable future, there will be more mentions of addListenerForSingleValueEvent than of the new get() method.

如上所述: addListenerForSingleValueEvent 方法一直是Firebase Android SDK的一部分,只要它存在就可以,并且用于从数据库中读取一次值.它是通过以下方式实现的:

As said: the addListenerForSingleValueEvent method has been part of the Firebase Android SDK for as long as it exists, and is used to read a value from the database once. It does this by:

  1. 使用 addValueEventListener
  2. 附加侦听器
  3. 等待该值从持久层显示出来
  4. 调用 onDataChange
  5. 删除监听器

这确实非常有效...直到我们在SDK 2.0版中引入了磁盘缓存(可追溯到I/O 2015).在此之前,步骤2中的所有值都将始终来自服务器,这要么是因为客户端已经有一个侦听器,要么是因为它将第一个侦听器附加到服务器.但是,使用磁盘缓存时,如果您以前已经读取了该值,但是当前没有侦听器,则第2步将从磁盘缓存中读取该值,并且您的 onDataChange 将立即使用该值进行调用.即使此后服务器上的值已更新.实际上,在后台,侦听器将更新磁盘缓存中的值,但仅在使用缓存中的(可能是过时的)值调用 onDataChange 之后.

This worked really well... until we introduced disk caching in version 2.0 of the SDK (way back at I/O 2015). Before that, all values in step 2 would always come from the server, either because the client already had a listener, or because this would attach the first listener to the server. But with disk caching, if you had previously read the value but currently had no listener to it, step 2 will read the value from the disk cache, and your onDataChange will be called with that value immediately. Even if the value on the server has been updated since. In fact, behind the scenes the listener will update the value in the disk cache, but only after calling your onDataChange with the (possibly stale) value from the cache.

虽然可以解释这种行为,但这并不是几乎任何人都想要的.不幸的是,我们发现这种边缘情况为时已晚,无法将其归类为简单的实现错误并加以修复.因此,我们将其保留下来,建议人们要么使用磁盘持久性要么使用 addListenerToSingleValueEvent ,但不要同时使用.或者,您可以在相同的引用/查询上调用 keepSynced(true)作为解决方法.都杂乱无章,不好.

While this behavior can be explained, it is not what almost anyone wanted. Unfortunately we found this edge case too late to classify it as a simple implementation bug and fix it. So we left it in, and recommended that folks either use disk persistence or use addListenerToSingleValueEvent, but not both. Or you could call keepSynced(true) on the same reference/query as a workaround. All messy, and not good.

快进5年以上,我们终于推出了一种不再具有这种笨拙行为的新方法.而且自2015年以来,Android API已有相当长的发展,因此我们还使用了(略微)更现代的方法签名: Task< DataSnapshot>get().

Fast forward 5+ years, and we finally introduced a new method that doesn’t have this awkward behavior anymore. And since Android APIs have moved on quite a bit since 2015, we also use a (slightly) more modern method signature: Task<DataSnapshot> get().

这篇关于get()和addListenerForSingleValueEvent有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆