【发布时间】:2014-12-08 14:23:07
【问题描述】:
使用 Firebase for Android,我将以下数据结构用于具有有限数量槽的聊天室:
/rooms
/<roomid, generated by push()>
/users
one: null
two: null
three: null
为了让我的客户占据其中一个插槽(one 到 three),我使用以下代码 as provided here (JavaScript version):
var userid = "myuserid";
var ref = new Firebase("<my-firebase>.firebaseio.com/rooms/<roomid>/users");
ref.transaction(function(users) {
if (!users.one) {
// Claim slot 1
users.one = userid;
return users;
} else if (!users.two) {
// Claim slot 2
users.two = userid;
return users;
} else if (!users.three) {
// Claim slot 3
users.three = userid;
return users;
}
// Room is full, abort the transaction.
return;
}, function(err, committed, snapshot) {
if (committed && !err) {
// Joined room successfully.
} else {
// Could not join room because it was full.
}
});
经过一些测试,我发现这不起作用。我对以下两个解释它为什么不起作用的假设是否正确?
- 在
runTransaction(...)(Android) 或transaction(...)(JavaScript) 中,您必须将可选参数fireLocalEvents(Android) 或applyLocally(JavaScript) 设置为false,否则您将收到来自交易虽然可能不成功。 - 即使将
fireLocalEvents(Android) 或applyLocally(JavaScript) 设置为false,该引用上onChildChanged(...)的事件也会触发之前您的事务在@987654335 中成功返回@。这是预期的行为吗?
对于这种特殊情况,这意味着我将收到聊天室已满的通知(ChildEventListener.onChildChanged(...))在我知道 我自己我是获得最后一个位置的人(Transaction.Handler.onComplete(...))。
假设,如果房间已满……
- 我在那里找到了一个插槽,执行了一些代码并启动了一些新的东西。
- 我没有获得任何插槽,我只想从列表中隐藏房间(因为它不再可用)。
如果我想这样做,我必须将它的完整逻辑移至ChildEventListener.onChildChanged(...),因为那是我将首先收到事件的地方,对吗?否则,在我知道我是最后一个空位之前,房间就会被隐藏起来。
有什么想法吗?
【问题讨论】:
-
看起来很直观,onchildchanged 会在 oncomplete 之前触发。
-
@danny117 为什么?在服务器实际告诉您导致更改的事务成功完成之前,服务器会通知您有关数据更改的信息?如果我在事务处理程序中打开本地事件,我会同意。但事实上,并非如此。这就是
fireLocalEvents标志的用途。 -
onComplete 好像完成了?
-
@danny117 所以是的,在事务完成之前数据不应该更新。看来你同意了。
标签: android firebase firebase-realtime-database