将数据添加到FireBase实时数据库中的列表的最佳方法是什么

时间:2018-10-09 10:16:19

标签: android firebase firebase-realtime-database

我正在使用firebase实时数据库,并且正在将字符串列表存储在特定的存储引用中。当前,要向列表中添加内容

我正在执行以下步骤。

  1. 读取数据库子引用
  2. 获取数据快照并检查其是否为空(这意味着首先 时间)
  3. 如果为空,请直接设置您的本地列表
  4. 如果dataSnapshot.getValue();不为null,则(已经存在 db,因此需要在其末尾附加新数据。)         将远程列表从dataSnapshot.getValue();保存到本地变量。

    然后将新数据添加到其末尾

  5. 现在本地列表包含远程和新项目中的所有项目 项目。将此保存到子引用中

下面是我为此编写的代码

DatabaseReference reference = root()
        .child(userId)
        .child(list_id);
reference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        reference.removeEventListener(this);
        List<String> value = new ArrayList<>();
        if (dataSnapshot.getValue() == null) {
            value.add(message);
        } else {
            if (dataSnapshot.getValue() instanceof List && ((List) dataSnapshot.getValue()).size() > 0 && ((List) dataSnapshot.getValue()).get(0) instanceof String) {
                value = (List<String>) dataSnapshot.getValue();
                value.add(message);
            }
        }
        reference.setValue(value, (databaseError, databaseReference) -> {
            finish();
        });
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        finish();
    }

     private void finish() {
        Log.e(TAG,"save finished");
    }
});

这是执行简单操作的许多步骤。而且,一直以来,我都是从远程提取整个数据并将新数据附加到它上面。

有没有简单的方法可以做到这一点?我尝试了如下的“ push()”方法

DatabaseReference reference = root()
    .child(userId)
    .child(list_id).push();

但是它总是向我添加的值添加新的键。任何人都可以解释用更少的代码实现此目标的正确方法是什么?

更新:
我的数据库结构如下所示

enter image description here

2 个答案:

答案 0 :(得分:1)

您提供的解决方案非常好,但是为什么要删除回调中的侦听器呢? 我将为您编写代码以使其更简单。请在下面查看:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference listIdRef = rootRef.child("list").child(list_id);
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        List<String> list = new ArrayList<>();
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String comment = ds.getValue(String.class);
            list.add(comment);
        }
        //Do what you need to do with your list
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage());
    }
};
listIdRef.addListenerForSingleValueEvent(valueEventListener);

不要忽略错误。

无需获取实体列表即可在08-10-18节点中添加新子级的最简单方法是仅使用以下代码行:

Map<String, Object> map = new HashMap<>();
map.put("5", "comment55");
rootRef.child("list").child(list_id).updateChildren(map);

但是,甚至更好的解决方案是使用push()方法代替列表,地图和子项。因此您的数据库结构应如下所示:

Fireabase-root
    |
    --- usr100
          |
          --- 08-10-18
                |
                --- randomId: "comment1"
                |
                --- randomId: "comment2"
                |
                --- randomId: "comment3"
                |
                --- randomId: "comment4"

代码应如下所示:

String key = rootRef.child("list").child(list_id).push().getKey();
Map<String, Object> map = new HashMap<>();
map.put(key, "comment5");
rootRef.child("list").child(list_id).updateChildren(map);

在这种情况下,您不必担心密钥,它不再是数字。在没有push()方法帮助的情况下,您需要获取整个列表,如我的答案的第一部分所述,添加新元素并更新数据库中的列表。

答案 1 :(得分:0)

这只是对我已经尝试并正在工作的现有已接受答案的更新。这是相同的过程,只需要较少的代码行,而不使用已接受的答案中提到的ValueEventListenerupdateChildren方法。

     DatabaseReference reference = deviceRootReference().child(userId).child(list_id).push();
     Map<String, Object> map = new HashMap<>();
     map.put(reference.getKey(), comment);
     Tasks.await(reference.updateChildren(map));

注意:此代码同步执行数据库写操作(Tasks.await阻止线程),因此上面的代码段应仅在后台线程中运行