安卓Firebase数据库事务

3
  ATNRef= FirebaseDatabase.getInstance().getReference("AvailableTokenNumber");
                ATNRef.runTransaction(new Transaction.Handler() {
                    @Override
                    public Transaction.Result doTransaction(MutableData mutableData) {

                        if (mutableData.getValue(int.class ) == 0){
                            mutableData.setValue(2);
                            data.tokenNo = 1;
                            return Transaction.success(mutableData);

                        }else {
                            data.tokenNo=mutableData.getValue(int.class);
                            mutableData.setValue(data.tokenNo + 1);
                            return Transaction.success(mutableData);
                        }
                    }

每当代码第一次运行时,data.tokenNo的值为0。之后,它会根据数据库中的值正确更新。
我无法确定是什么原因导致每次应用程序/代码首次运行时data.token的值为0。
2个回答

5

在执行事务的初次运行时,您应该预期可用数据的初始快照可能为 null。请注意这个来自文档

注意:由于 doTransaction() 被多次调用,它必须能够处理 null 数据。即使您的远程数据库中存在数据,当事务函数运行时,它可能没有被本地缓存,导致初始值为 null。

同样在javadoc中也有所提及:

此方法将被调用,并可能被多次调用,具体取决于此位置上的当前数据。

请预期您的处理程序第一次运行时,它会处理一个空的数据库。然后,当该位置上的数据已知(如果有),您应该准备好处理那种情况。如果您不想在位置上没有数据(或未知数据)时执行任何操作,只需以无对 mutableData 的更改产生成功的 Transaction。


这个可以运行。但是数据不能实时反映出来。当从数据库检索数据时,最初显示为0。在与UI元素进行某些交互(如按按钮或恢复)之后,“0”会更改为数据库中的实际值。而且,这不仅发生在第一次访问数据库时,每次检索数据时都会发生。如何避免这种情况?如何在第一次就显示实际数据? - Gaurav Singh
我不确定你的意思。当事务完成时,数据将被写入,所有客户端都应该能够看到它。 - Doug Stevenson
希望这可以帮助您理解问题。考虑以下情况:(A)数据库中的值为3,(B)事务操作,(C)应用程序中显示的值为0(错误数据),(D)我按下某个按钮或刷新了页面,(F)现在应用程序中的值更改为3(正确数据)。 - Gaurav Singh
如果您想实时查看某些数据的更新,您需要在该数据上拥有一个活动监听器,并相应地对这些更改进行反应。事务不会改变监听器的工作方式。 - Doug Stevenson

1
感谢您的解释,@Doug Stevenson。 我从您的答案中理解了这种情况。
然后我用这个方法解决了这个问题。 至少对我来说有效。
FirebaseDatabase database = FirebaseDatabase.getInstance();
try {
    database.setPersistenceEnabled(true);
} catch (Exception e) {
    // ignore
}

...

DatabaseReference ref = database.getReference("somewhere");

// Read value from database to synchronize localDB with remoteDB
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

    // Then execute transaction.
    ref.runTransaction(new Transaction.Handler() {
      @NonNull
      @Override
      public Transaction.Result doTransaction(@NonNull MutableData mutableData) {
        ...
        return Transaction.success(mutableData);
      }


      @Override
      public void onComplete(@Nullable DatabaseError databaseError, boolean committed, @Nullable DataSnapshot dataSnapshot) {
        ...
      }

    });
  }
});

谢谢,你能解释一下 database.setPersistenceEnabled(true) 的意思吗? - Yo Apps

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接