使用ViewModel和LiveData时如何修改Firebase Realtime Database指定子节点值
实现方案
你只需要在已封装的UsersViewModel中新增写入逻辑,视图层直接调用ViewModel暴露的公开方法即可,不需要修改现有读取逻辑,也不需要在视图层引入数据库引用。
步骤1:修改UsersViewModel新增更新方法
我们优先使用Firebase的updateChildren方法实现局部字段更新,避免覆盖其他未修改的子节点:
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() // 可选:新增写入状态的LiveData,方便视图层感知写入结果 private val _writeStatus = MutableLiveData<Boolean?>() val writeStatus: LiveData<Boolean?> get() = _writeStatus 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 } // 方法1:仅更新lastName字段的专用方法 fun updateLastName(newLastName: String) { USERS_REF.child("lastName").setValue(newLastName) .addOnCompleteListener { task -> _writeStatus.postValue(task.isSuccessful) } } // 方法2:更通用的多字段更新方法,可按需传入要修改的任意字段 fun updateUserFields(updateMap: Map<String, Any>) { USERS_REF.updateChildren(updateMap) .addOnCompleteListener { task -> _writeStatus.postValue(task.isSuccessful) } } // 可选:重置写入状态,避免重复消费回调 fun resetWriteStatus() { _writeStatus.value = null } }
步骤2:在Activity/Fragment中调用更新方法
视图层直接调用ViewModel暴露的方法即可,无需感知底层数据库实现:
// 示例:点击按钮修改lastName updateLastNameBtn.setOnClickListener { val newLastName = lastNameEditText.text.toString() // 调用专用方法更新 usersViewModel.updateLastName(newLastName) // 也可以用通用方法更新,比如同时修改firstName和lastName // val updateMap = mapOf( // "firstName" to "新的名字", // "lastName" to "新的姓氏" // ) // usersViewModel.updateUserFields(updateMap) } // 可选:监听写入结果,给用户反馈 usersViewModel.writeStatus.observe(this) { isSuccess -> isSuccess ?: return@observe if (isSuccess) { Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show() } else { Toast.makeText(this, "修改失败,请稍后重试", Toast.LENGTH_SHORT).show() } usersViewModel.resetWriteStatus() }
因为你已经在ViewModel中监听了对应节点的变化,写入成功后usersLiveData会自动收到最新数据,你的原有UI更新逻辑会自动触发刷新,不需要额外写更新UI的代码。
内容的提问来源于stack exchange,提问作者Tom Darious
相关产品推荐
相关产品推荐

