首页 > 解决方案 > 将字符串附加到 Firebase 实时数据库上的列表

问题描述

我想在 Firebase 实时数据库上的列表中附加一个字符串。(我的代码已经可以使用,但是有问题)

所以数据库看起来像这样:

message:
    0: "some string"
    1: "another string"
    2: "some string"

但我认为这段代码的问题是,如果有人读取消息的数量然后想要写一条消息,那么当另一个用户同时写一条消息时就会出现问题(因为消息的数量会改变)。

FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference("message");

myRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        myRef.child(
            String.valueOf(dataSnapshot.getChildrenCount())
            ).setValue("SOME STRING");
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {

    }
});

标签: androidfirebasefirebase-realtime-database

解决方案


出于几个原因,尝试在多用户 Firebase 中使用顺序数字索引(通常也称为数组索引或自动增量值)是一种反模式。

  • 正如您自己已经注意到的那样,用户有可能会覆盖彼此的数据。但是,这可以通过使用 transaction来解决,如果您需要基于其现有值来属性值,这是一种可行的方法。JavaScriptDatabaseReference.transaction方法的参考文档有这个示例,这正是您所需要的:

    // Increment Ada's rank by 1.
    var adaRankRef = firebase.database().ref('users/ada/rank');
    adaRankRef.transaction(function(currentRank) {
      // If users/ada/rank has never been set, currentRank will be `null`.
      return currentRank + 1;
    });
    

    Android 中的语法稍微复杂一些,但工作方式相同。

  • 当一个事务工作时,这意味着应用程序只有在用户连接到服务器时才能工作。当他们离线时,交易将失败。

由于这些原因,Firebase 应用通常使用不同的机制来生成其密钥。API的内置push()方法会生成一个唯一的、始终递增的密钥。虽然此键不如您的顺序数字键可读,但它们确实解决了上述两个问题,而无需您自己编写更多代码。添加push()消息变得如此简单:

final DatabaseReference myRef = database.getReference("message");
myRef.push().setValue("SOME STRING");

请注意,这个主题已经涵盖了很多,所以我建议您也检查一下:


推荐阅读