我使用Firebase SDK for Java / Android的多人游戏有4个玩家可以一起玩的游戏室。
为了实现配对,我为每个玩家可以加入的房间提供了Firebase参考。这些引用中的每一个都有4个插槽(作为子节点),其中包含正在参与的播放器的UUID或者如果插槽仍然可用则为空字符串。
为了防止两个(或更多)玩家同时声称同一个广告位,我正在使用交易。以下代码是否正确用于此目的?
private int mUserSlot;
firebaseReference.runTransaction(new Transaction.Handler() {
@Override
public Result doTransaction(MutableData currentData) {
for (int s = 0; s <= 3; s++) { // loop through all slots
final String slotValue = currentData.child(slotFromLocalID(s)).getValue(String.class);
if (slotValue == null || slotValue.equals("") || slotValue.equals(mUserUUID)) { // if slot is still available
currentData.child(slotFromLocalID(s)).setValue(mUserUUID);
mUserSlot = s;
return Transaction.success(currentData);
}
}
return Transaction.abort();
}
@Override
public void onComplete(FirebaseError error, boolean committed, DataSnapshot currentData) {
if (error == null) {
if (committed) {
System.out.println("User is now in slot "+mUserSlot);
}
else {
System.out.println("User could not join, all slots occupied");
}
}
else {
System.out.println("Error: "+error.getMessage());
}
}
});
但是,我在上面Exception
的{{1}}分支中抛出error != null
进行调试,经过一些测试运行后,我看到以下错误消息(来自{{1}在我的调试日志中:
onComplete()
这究竟是什么意思?我认为这些事务是为了防止并发访问相互覆盖的相同字段。这是否意味着应用程序的其他部分是在没有事务的情况下写入字段?
在这种情况下,我可以像处理error.getMessage()
一样处理它吗?这意味着,在这两种情况下,交易完成后我想写的价值都不存在,这是正确的吗?
答案 0 :(得分:3)
是的,该消息表示您的某个客户使用set
而不是transaction
写入同一位置,从而中止该交易。我强烈建议不要在使用交易的地方使用set
。