android 如何通过Firebase - Realtime中的setValue更新和获取ServerValue.increment操作?

y1aodyip  于 2022-12-28  发布在  Android
关注(0)|答案(1)|浏览(122)

我可以看到.runTransaction选项有一个返回快照的完成侦听器,因此我假设此快照是客户端刚刚执行的updated快照(“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);

我的猜测是使用setValue(ServerValue.increment)比runTransaction快一个数量级。
问题是,似乎不可能检索结果,因为似乎没有任何侦听器可靠地返回客户机更新的值。

/**
   * ...
   * @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);
  }

在这里,文档承诺侦听器将给予我“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);
  }

注意,DatabaseReference在值更新时不是分支的“快照”,而是一个实时引用...
因为返回了一个普通引用,所以我假设我们必须将一个普通的singleValueEventListener连接到此引用...这意味着此读取不是原子的...
所以有几种方法可能有效,但我不确定:

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)

                                    }
                                }
                            }
                    );

或者也许没有可靠的方法来原子化地做这件事。
因此,setValue和updateChildren可能可以与ServerValue.increment操作符一起正常工作...但是正确执行updateAndGet的方法只能通过runTransaction()??来实现。

wfveoks0

wfveoks01#

当您对服务器上已经存在的内容不感兴趣时,可以使用ServerValue.increment()来增加字段的值。如果您需要根据已经存在的值执行某些操作,则确实需要执行事务,该事务首先读取数据,然后立即执行更新。
第一个解决方案是事务的简化版本,它不需要与Firebase服务器进行往返通信。
当您想要读取由多个用户递增的字段的值时,您应该附加一个持久性侦听器,这样您就可以得到实时通知。

相关问题