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

查看:34
本文介绍了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 实时数据库最适合用于通过以下方式保持客户端和数据库服务器(或多个客户端之间)之间的数据同步使用长期存在的侦听器.在 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 中是:

And in Kotlin it is:

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.

我们当然会更新文档.但是我们无法更新所有教程.因此,在可预见的未来,addListenerForSingleValueEvent 的提及次数将多于新的 get() 方法.

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 版中引入了磁盘缓存(早在 2015 年 I/O 时).在此之前,第 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 年多,我们终于推出了一种新方法,不再有这种尴尬的行为.由于 Android API 自 2015 年以来发生了相当大的变化,我们还使用了(稍微)更现代的方法签名:Taskget().

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天全站免登陆