如何在Firebase中更新特定用户的ArrayList且避免重载用户对象?
解决Firebase更新用户列表时覆盖整个对象的问题
嘿,我猜你现在遇到的问题是每次往用户的字符串列表里加内容时,整个User对象都被重新写入数据库了——这大概率是因为你直接创建了新的User实例,然后用setValue()把它覆盖到数据库里,而不是只更新列表字段对吧?
问题根源
当你新建一个User userOne = new User();然后只设置userAdd(假设这是你的列表字段),再调用setValue(userOne)时,Firebase会把这个新对象完全替换掉数据库里原有的用户记录,相当于把整个用户对象重新加载/覆盖了,这肯定不是你想要的。
解决方案1:只更新列表字段(适合需要维护有序列表的场景)
我们可以先读取当前用户的列表数据,追加新内容后,只更新这个特定字段,而不是整个User对象:
private void saveSelectionInDatabase(){ String text = selectionSpinner.getSelectedItem().toString(); FirebaseUser firebaseUser = firebaseAuth.getCurrentUser(); // 先判断用户是否已登录,避免空指针 if(firebaseUser == null) { Log.w("Firebase", "User not logged in"); return; } // 获取当前用户在数据库的引用 DatabaseReference userRef = FirebaseDatabase.getInstance() .getReference("users") .child(firebaseUser.getUid()); // 一次性读取当前的列表数据 userRef.child("selectedItems") // 这里换成你实际的列表字段名 .addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { // 初始化列表,如果已有数据就转换过来 List<String> currentItems = new ArrayList<>(); if(snapshot.exists()){ // 用GenericTypeIndicator来正确解析List类型 currentItems = snapshot.getValue(new GenericTypeIndicator<List<String>>() {}); } // 添加新选中的内容 currentItems.add(text); // 只更新列表字段,不会影响用户对象的其他属性 userRef.child("selectedItems").setValue(currentItems); } @Override public void onCancelled(@NonNull DatabaseError error) { Log.e("Firebase", "Failed to fetch current list", error.toException()); } }); }
解决方案2:用push()直接添加元素(更高效,适合无需严格顺序的场景)
如果你的列表不需要严格保持顺序,或者可以接受Firebase生成的唯一键,那直接把列表做成子节点,用push()新增元素就好——这种方式不需要先读取整个列表,减少网络请求,也完全不会覆盖现有数据:
private void saveSelectionInDatabase(){ String text = selectionSpinner.getSelectedItem().toString(); FirebaseUser firebaseUser = firebaseAuth.getCurrentUser(); if(firebaseUser == null) { Log.w("Firebase", "User not logged in"); return; } DatabaseReference userRef = FirebaseDatabase.getInstance() .getReference("users") .child(firebaseUser.getUid()); // 直接在selectedItems子节点下新增元素,Firebase会自动生成唯一ID userRef.child("selectedItems").push().setValue(text); }
额外注意事项
- 确保你的Firebase安全规则允许用户修改自己的节点,比如:
{ "rules": { "users": { "$uid": { ".read": "$uid === auth.uid", ".write": "$uid === auth.uid" } } } } - 永远不要用空的
User对象去调用setValue(),除非你明确要清空用户的所有数据。
内容的提问来源于stack exchange,提问作者Nikolai Peram
相关产品推荐
相关产品推荐

