Java 参与人数有限的Firebase房间

Java 参与人数有限的Firebase房间,java,android,real-time,firebase,Java,Android,Real Time,Firebase,在中,创建聊天室之类的“房间”很容易,正如在他们的各种示例中记录的那样 对于聊天室的数据结构,我将使用如下内容: rooms room1 member_count members user1 user2 messages message1 但是现在我想对每个聊天室的参与者数量进行限制,比如说每个聊天室有3个用户 你怎么能做到这一点 在他们的文档中,看起来最有希望的一件

在中,创建聊天室之类的“房间”很容易,正如在他们的各种示例中记录的那样

对于聊天室的数据结构,我将使用如下内容:

rooms
    room1
        member_count
        members
            user1
            user2
        messages
            message1
但是现在我想对每个聊天室的参与者数量进行限制,比如说每个聊天室有3个用户

你怎么能做到这一点

在他们的文档中,看起来最有希望的一件事就是使用。你能证实这是一个好办法吗?还是这是错误的方法

像这样的解决方案怎么样

Firebase countRef = new Firebase("https://mychat.firebaseIO-demo.com/rooms/room1");
countRef.runTransaction(new Transaction.Handler() {
    @Override
    public Transaction.Result doTransaction(MutableData currentData) {
        int oldMemberCount = currentData.child("member_count").getValue(Integer.class);
        currentData.child("member_count").setValue(oldMemberCount + 1); // try to update member count
        return Transaction.success(currentData);
    }

    @Override
    public void onComplete(FirebaseError error, boolean committed, DataSnapshot currentData) {
        if (error != null || !commited) {
            // rollback value (how? just do nothing?)
        }
        else {
            // transaction has been commited (value has already been saved?)
            currentData.child("members").child(CURRENT_USER_UUID).setValue(CURRENT_USER_NAME); // add user to the members list
        }
    }
});
如果您能对这种方法发表评论,那就太好了。此外,如果交易失败,人们当然无法满足于这种情况。用户仍然希望加入,无论同时有其他用户试图加入。那你该怎么办?将此代码放入函数中,并在出现错误时再次调用该函数

编辑:

要创建具有自动唯一ID的新房间,您当然可以在
Firebase
参考上使用

但是,如果您想向该会议室添加成员,上述问题仍然存在。另一种解决方案是在加入时在成员列表中设置用户的名称。当将优先级设置为当前时间戳时,可以将成员列表回调为3(成员)。但这似乎既不优雅也不干净。

如果每个房间的参与者数量固定(且相对较少),最好使用事务。但是,最好为聊天室中的每个人创建命名良好的对象,例如:

/rooms
  /<roomid, generated by push()>
    /users
      one: null
      two: null
      three: null

您可以通过Firebase的图形调试器Forge上传这些规则,您应该可以开始了

难道你不能读取members\u count的值,如果该值小于3,那么“join”else“abort”吗?不,如果两个客户端试图同时加入,它们都会将members\u count设置为4并加入。在那之后,实际上有5个客户在房间里。这种情况很可能出现在实时应用程序中,不是吗?如果你在它们连接之前和连接之后都做了检查,你会没事的。正如你所知,Firebase不是实时的3000毫秒。它们真的很快,但不像你所说的30毫秒延迟。如果您需要这样快的速度,您需要一个服务器,它执行逻辑,而不使用Firebase。但一个可行的解决方案是创建一个securityrule,它禁止在
val().children().length==2时写入。这将正常工作。您不需要30毫秒的实时数据来查看冲突。使用Firebase时,客户端总是存储数据集的本地副本,然后自动与服务器版本同步。我并不是在编这个例子,但Firebase确实明确地暗示了这个问题,并建议在他们的文档中使用事务,正如我所发布的:这绝对是一个好办法。问题只是我提议的实现是否可以,因为它比Firebase在他们的文档中给出的简单示例要复杂一些。非常感谢!这正是我的意思:)但为什么安全规则是必要的?从关于事务的文档(如果
没有其他人修改过它,则事务成功,并调用您的完成回调。否则,如果存在冲突,Firebase客户端将检索新值并重新运行更新函数
),我了解到您可以在没有安全规则的情况下使用事务,因为只有他们才能确保没有其他人修改数据。如果有人这样做了,您首先会得到新的值,然后可以再次检查房间是否为空。这是错误的吗?我这样问是因为如果用户可以再次离开频道,其他人可以申请他的位置,那当然是非常好的。如果没有安全规则,这是可能的。但是使用安全规则,您无法将自己从插槽中移除,因为数据一到插槽中,
write
权限就消失了,对吗?没错,安全规则只用于防止恶意客户端占据其他人的位置。但是,正如你所指出的,这也意味着你不能离开房间。您可以删除安全规则以实现这一点,或者如果您正在通过某种身份验证机制登录用户,则可以将规则更改为“!data.exists()| | auth.id==data.val()”,以确保只有声明了该点的用户才能删除自己。