【问题标题】:Android Java Firebase runTransaction deletes values when classes are not exactly the sameAndroid Java Firebase runTransaction 在类不完全相同时删除值
【发布时间】:2020-11-26 14:15:00
【问题描述】:

我在运行 runTransaction 函数来更新值时遇到问题,当类不同时,此函数会从类中删除值 让我试着解释一下

关于我的 userModel 类 应用程序版本 1.0 具有具有以下属性的用户模型

-用户名 -uid -追随者

应用程序版本 1.1 具有具有以下属性的用户模型 -用户名 -uid -追随者

  • 状态(已添加)

所以 userModel 多了一个属性

当使用 appVersion 1.0 的用户现在对使用 appVersion 1.1 的用户运行事务时(例如,在关注时,我将关注者增加 1),用户 1.0 完成的事务仅设置其当前版本中的值,因此删除 1.1 版用户的状态

我的代码

API.ref.databaseSpecificUser(id).runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(final MutableData mutableData) {
            final User user = mutableData.getValue(User);

            if (user== null) {
                return Transaction.success(mutableData);
            }

            .....

            mutableData.setValue(user);
            return Transaction.success(mutableData);
        }

mutableData.setValue(user);

更新值但不设置状态,因为应用程序版本 1.0 在其 userModel 类中不包含“STATUS”

有什么想法吗?

【问题讨论】:

  • 这种行为听起来符合我的预期:数据库不知道您的应用程序的版本,因此当您的事务在该位置设置数据时,它只是执行该指令并写入数据。你想让它做什么呢?
  • 如果我们能看到为交易提供实际数据的代码,这也将非常有帮助,因为它可以让我们想出另一种方式来完成您想要的事情。
  • 我只想更新必要的数据,而不是这个参考下的全部数据。奇怪的是,如果对我的 iOS 版本做同样的事情,提供相同的代码,它不会删除任何数据。目前这真的很糟糕,因为我以后可能会向 userModel 添加更多属性,但是使用旧版本的人会删除它们...
  • 事务在该位置设置整个值,因此该方法被称为setValue。这应该适用于所有平台。如果您想执行部分更新,您将调用updateChildren 仅传入需要修改的子项。如果您只想更新单个属性,我建议您仅在该节点/属性上运行事务,而不是在整个用户上运行。如果你想简单地增加一个值,我建议使用ServerValue.increment(1) - 这是今年早些时候添加到 API 中的。
  • 我正在使用 runTransaction,因为它在增加值时由 firebase 建议。但正如我正确理解的那样,如果我使用事务,则不可能只更新更改的值,对吗?感谢您的帮助!

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


【解决方案1】:

事务必须为您运行它的位置提供完整的新值。您不能在 API.ref.databaseSpecificUser(id) 上运行事务,然后只为其下的单个属性提供值。

您的方案中有几个选项:

  1. 不要使用(不完整的)User 类来调用setValue(),而只能直接更新mutableData 上的特定属性。所以这就像mutableData.child("count").setValue(42)。这样mutableData 仍将包含所有属性,即使User 类不包含。

  2. 直接在要修改的属性上运行事务,例如:API.ref.databaseSpecificUser(id).child("count").runTransaction(...。这样mutableData 将仅用于您正在修改的属性,因此不会删除任何其他内容。在这里,您也不会使用 User 类,因为您正在读取/写入单个属性。

  3. 使用较新的ServerValue.increment(1) 操作来增加计数。此操作效率更高,并且通常会导致更简单的代码。比如:ServerValue.increment(1).child("count").setValue(ServerValue.increment(1));

【讨论】:

  • 非常感谢我什至不知道新功能!我将尝试根据此改进我的代码。还有一个/最后一个问题:ServerValue.increment 函数将如何改变我的数据消耗?是不是比我使用runTransaction方法的时候少?
  • 所以我只是用我的 .runTransaction func 再次测试它:我的 android 方法正在删除未知值,而我的 iOS 应用程序没有,但完全相同。
  • 我想我知道他们为什么会有不同的行为。在我的 iOS 版本中,我获取可变数据并选择特定值来更改它们。最后,我将值设置为新值。在我的 android 版本中,我得到 Post.class 因此忽略不存在的值。保存它会导致删除类未知的值!感谢您的回复,我找到了解决问题的方法!
  • 很高兴听到你想通了。我试图解释 User 类在我的回答中的选项 1 和 2 中导致了您的问题。
  • 如果您只需要增加一个值,ServerValue.increment() 操作将比运行事务更快。有关这方面的更多信息,请参阅stackoverflow.com/questions/61536203/…
猜你喜欢
  • 2017-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 2016-11-02
  • 1970-01-01
相关资源
最近更新 更多