使用ViewModel和LiveData时如何删除Firebase Realtime Database数据
实现步骤
你只需要在现有UsersViewModel中新增公开的删除方法,直接调用持有的USERS_REF的removeValue()方法即可。因为你的FirebaseQueryLiveData已经绑定了该节点的变化监听,删除操作完成后usersLiveData会自动收到更新通知,UI层无需额外手动刷新数据。
1. 修改UsersViewModel新增删除方法
你可以根据需求选择删除整个用户节点,或者删除指定子节点,示例代码如下:
class UsersViewModel : ViewModel() { private val uid = Firebase.auth.currentUser!!.uid private val USERS_REF: DatabaseReference = FirebaseDatabase.getInstance().getReference("/users/$uid") private val liveData: FirebaseQueryLiveData = FirebaseQueryLiveData(USERS_REF) private val usersLiveData: MediatorLiveData<Users> = MediatorLiveData() init { usersLiveData.addSource(liveData, object : Observer<DataSnapshot> { override fun onChanged(dataSnapshot: DataSnapshot?) { if (dataSnapshot != null) { usersLiveData.postValue(dataSnapshot.getValue(Users::class.java)) } else { usersLiveData.value = null } } }) } @NonNull fun getUsersLiveData() : LiveData<Users> { return usersLiveData } // 新增:删除当前用户的整个节点 fun deleteCurrentUserNode(onComplete: (Boolean, String?) -> Unit) { USERS_REF.removeValue().addOnCompleteListener { task -> if (task.isSuccessful) { onComplete(true, null) } else { onComplete(false, task.exception?.message) } } } // 新增:删除当前用户节点下的指定子字段,比如删除"age"字段就传"age" fun deleteUserChildField(fieldName: String, onComplete: (Boolean, String?) -> Unit) { USERS_REF.child(fieldName).removeValue().addOnCompleteListener { task -> if (task.isSuccessful) { onComplete(true, null) } else { onComplete(false, task.exception?.message) } } } }
2. UI层调用示例
在观察了usersLiveData的Activity/Fragment中,需要触发删除操作时直接调用ViewModel的对应方法即可:
// 比如点击删除按钮时调用 deleteBtn.setOnClickListener { viewModel.deleteCurrentUserNode { isSuccess, errorMsg -> if (isSuccess) { Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show() // 这里不需要手动更新UI,usersLiveData收到null值会自动回调你之前的观察逻辑 } else { Toast.makeText(this, "删除失败:${errorMsg ?: "未知错误"}", Toast.LENGTH_SHORT).show() } } }
可选优化:修复原有FirebaseQueryLiveData的小问题
你现有代码的onInactive方法逻辑存在冗余:你先直接移除了监听器,又延迟2秒执行移除逻辑,实际上不需要重复调用,修改后逻辑更合理:
override fun onInactive() { super.onInactive() // 只需要延迟执行移除即可,不需要立刻移除 Handler(Looper.getMainLooper()).postDelayed(removeListener, 2000) listenerRemovePending = true }
这个优化不影响删除功能的正常使用,只是避免重复操作减少不必要的性能消耗。
内容的提问来源于stack exchange,提问作者Tom Darious
相关产品推荐
相关产品推荐

