简体   繁体   English

我如何通过 Firebase 中的 setValue 实时更新和获取 ServerValue.increment 操作?

[英]How could I update and GET a ServerValue.increment operation via setValue in Firebase - Realtime?

I can see the.runTransaction option has a completion listener which returns a snapshot, so I will assume this snapshot is the updated snapshot ("DataSnapshot currentData") that the client just performed.我可以看到 .runTransaction 选项有一个返回快照的完成监听器,所以我假设这个快照是客户端刚刚执行的更新快照(“DataSnapshot currentData”)。

@NonNull
public Result doTransaction(@NonNull MutableData currentData);

/**
 * This method will be called once with the results of the transaction.
 *
 * @param error null if no errors occurred, otherwise it contains a description of the error
 * @param committed True if the transaction successfully completed, false if it was aborted or
 *     an error occurred
 * @param currentData The current data at the location or null if an error occurred
 */
public void onComplete(
    @Nullable DatabaseError error, boolean committed, @Nullable DataSnapshot currentData);

My guess is that using a setValue(ServerValue.increment) is an order of magnitude faster than runTransaction.我的猜测是使用 setValue(ServerValue.increment) 比 runTransaction 快一个数量级。

The problem is, it seems the retrieval of the result is not possible, since there does not seem to be any listener that reliably returns the updated value by the client.问题是,似乎无法检索结果,因为似乎没有任何侦听器可以可靠地返回客户端更新的值。

  /**
   * ...
   * @param value The value to set at this location or null to delete the existing data
   * @param listener A listener that will be triggered with the results of the operation
   */
  public void setValue(@Nullable Object value, @Nullable CompletionListener listener) {
    setValueInternal(value, PriorityUtilities.parsePriority(this.path, null), listener);
  }

Here the documentation makes the promise that the listener will give me "the result of THE (MY??) operation", but when going to the listener it does not say that:这里的文档使 promise 听众会给我“ THE (MY??) 操作的结果”,但是当去听众时它并没有说:

  /**
   * This interface is used as a method of being notified when an operation has been acknowledged by
   * the Database servers and can be considered complete
   *
   * @since 1.1
   */
  public interface CompletionListener {

    /**
     * This method will be triggered when the operation has either succeeded or failed. If it has
     * failed, an error will be given. If it has succeeded, the error will be null
     *
     * @param error A description of any errors that occurred or null on success
     * @param ref A reference to the specified Firebase Database location
     */
    public void onComplete(
        @Nullable final DatabaseError error, @NonNull final DatabaseReference ref);
  }

Notice that the DatabaseReference is not a "snapshot" of the branch at the moment of value update, instead is just a live reference...请注意,DatabaseReference 不是值更新时分支的“快照”,而只是一个实时引用......

Because a plain reference is returned I assume we are forced to connect a plain singleValueEventListener to this reference.... which means this read will NOT be atomic...因为返回了一个简单的引用,所以我假设我们被迫将一个普通的 singleValueEventListener 连接到这个引用....这意味着这个读取不会是原子的...

So There are a couple methods that may work but Im not sure:所以有几种方法可能有效但我不确定:

Object db_config_ver = ServerValue.increment(1);

db_ver_ref.setValue(db_config_ver,
                            new DatabaseReference.CompletionListener() {
                                @Override
                                public void onComplete(@Nullable DatabaseError error, @NonNull DatabaseReference ref) {
                                    if (error == null) {

                                       //Should I connect a listener?? But this is NOT atomic and will bring ERRORS under heavy contention!!
                                        ref.addListenerForSingleValueEvent(
                                                new ValueEventListener() {
                                                    @Override
                                                    public void onDataChange(@NonNull DataSnapshot snapshot) {

                                                    }

                                                    @Override
                                                    public void onCancelled(@NonNull DatabaseError error) {

                                                    }
                                                }
                                        );

                                        //Maybe a simple proactive read will suffice?
                                        long value = ref.get().getResult().getValue(Long.class);

                                       //What If I read the ServerValue.increment() object here:
                                       System.out.println(db_config_ver)

                                    }
                                }
                            }
                    );

Or maybe there is NO reliable way to do this atomically.或者可能没有可靠的方法来自动执行此操作。

So maybe setValue and updateChildren may work properly with the ServerValue.increment operator... BUT the way to properly do an updateAnd Get can only be achieved with runTransaction()??所以也许 setValue 和 updateChildren 可以与 ServerValue.increment 运算符一起正常工作......但是正确执行 updateAnd Get的方法只能通过 runTransaction() 来实现?

You can use ServerValue.increment() to increment a value of a field when you are not interested in what already exists on the server.当您对服务器上已存在的内容不感兴趣时,可以使用ServerValue.increment()来增加字段的值。 If you need to perform some operations according to the value that already exists, then indeed you need to perform a transaction, which reads the data first and performs the update right after that.如果你需要根据已经存在的值进行一些操作,那么确实需要进行一个事务,先读取数据,然后再进行更新。

The first solution is a simplified version of a transaction, which doesn't need round-trip communications with Firebase servers.第一个解决方案是事务的简化版本,不需要与 Firebase 服务器进行往返通信。

When you want to read the value of a field that is incremented by multiple users, you should attach a persistence listener , so you can be notified in real-time.当你想读取一个字段被多个用户递增的值时,你应该附加一个持久化监听器,这样你就可以得到实时通知。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM