Firebase数据库Guest状态节点删除失败问题求助
Firebase数据库删除Guest的status字段未生效问题
我希望点击Check In按钮时删除Firebase数据库中Guest的status字段,但该操作未生效。相关代码如下:
ShareViewModel代码
class ShareViewModel: ViewModel() { var firstName : MutableState<String?> = mutableStateOf(null) private val _selectedGuest = MutableLiveData<Guest>() val selectedGuest: LiveData<Guest> get() = _selectedGuest fun setSelectedGuest(guest: Guest) { _selectedGuest.value = guest } // 更新Firebase中访客状态 fun updateGuestStatus(status: String) { val currentGuest = _selectedGuest.value currentGuest?.let { it.status = status updateStatusInFirebase(it) _selectedGuest.value = it } } // 删除Firebase中访客的status字段 fun deleteGuestStatus() { val currentGuest = _selectedGuest.value currentGuest?.let { it.status = ""// 原计划通过设空标记删除 Log.d("DeleteGuestStatus", "Deleting status for guest: ${it.id}") updateStatusInFirebase(it) _selectedGuest.value = it } } // 获取访客当前状态 fun getGuestStatus(): String? { return _selectedGuest.value?.status } private fun updateStatusInFirebase(guest: Guest) { val user = FirebaseAuth.getInstance().currentUser val userUid = user?.uid if (userUid != null) { val database = FirebaseDatabase.getInstance() val guestsRef = database.getReference("users/$userUid/guests") // 假设guest.id是访客的唯一标识 val guestId = guest.id // 使用setValue(null)删除status字段 guestsRef.child(guestId).child("status").setValue(null) } } }
SecurityScreen代码
@Composable fun SecurityScreen(navController: NavController, shareViewModel: ShareViewModel) { var guests by remember { mutableStateOf<List<Guest>>(emptyList()) } var selectedGuest by remember { mutableStateOf<Guest?>(null) } val database = FirebaseDatabase.getInstance() val usersRef = database.getReference("users") LaunchedEffect(usersRef) { // 添加所有用户数据的监听 usersRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val allGuests = mutableListOf<Guest>() // 遍历每个用户的访客列表 for (userSnapshot in snapshot.children) { val guestsSnapshot = userSnapshot.child("guests") for (guestSnapshot in guestsSnapshot.children) { val guest = guestSnapshot.getValue(Guest::class.java) guest?.let { allGuests.add(it) } } } // 更新访客列表 guests = allGuests } override fun onCancelled(error: DatabaseError) { // 处理错误 } }) } fun deleteGuestStatus(guest: Guest) { shareViewModel.setSelectedGuest(guest) shareViewModel.deleteGuestStatus() } Column(modifier = Modifier.padding(16.dp)) { Text( text = "Security Department", modifier = Modifier .padding(bottom = 16.dp) .fillMaxWidth(), fontSize = 20.sp, fontWeight = FontWeight.Bold, textAlign = TextAlign.Center ) LazyColumn( content = { items( items = guests.chunked(4), // 每一行显示4个访客 itemContent = { rowItems -> Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) { rowItems.forEach { guest -> GridItem( guest = guest, onClick = { selectedGuest = guest }, onCheckInClick = { deleteGuestStatus(guest) } ) } } } ) } ) // 点击访客卡片后显示详情弹窗 selectedGuest?.let { guest -> Dialog( onDismissRequest = { selectedGuest = null }, properties = DialogProperties( dismissOnBackPress = true, dismissOnClickOutside = true ) ) { Column( modifier = Modifier .padding(16.dp) .clip(RoundedCornerShape(10.dp)) .background(MaterialTheme.colorScheme.background) .fillMaxWidth() ) { Text( text = "Name: ${guest.name}", fontSize = 18.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(8.dp) ) Text( text = "Contact: ${guest.phoneNumber}", fontSize = 18.sp, modifier = Modifier.padding( start = 8.dp, end = 8.dp, bottom = 16.dp ) ) Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier, ) { TextButton(onClick = { // 点击Check In时删除status字段 deleteGuestStatus(guest) }) { Text(text = "Check In", fontSize = 20.sp, fontWeight = FontWeight.Bold,) } Spacer(modifier = Modifier.weight(1f)) TextButton(onClick = { /*TODO*/ }) { Text(text = "Check Out", fontSize = 20.sp, fontWeight = FontWeight.Bold,) } } } } } } } @Composable fun GridItem(guest: Guest, onClick: () -> Unit, onCheckInClick: () -> Unit) { Card( shape = CircleShape, colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.primary ), modifier = Modifier .size(75.dp) .padding(8.dp) .clickable(onClick = onClick) ) { Text( text = guest.randomNumbers.joinToString(","), modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center), fontSize = 18.sp, fontWeight = FontWeight.Bold, textAlign = TextAlign.Center, color = MaterialTheme.colorScheme.onPrimary ) } }
数据库截图

问题分析与解决方法
核心问题
当前updateStatusInFirebase方法用当前登录用户的uid构建数据库路径,但SecurityScreen的逻辑是遍历所有用户的访客数据,点击的访客可能属于其他用户,导致路径错误,无法定位到目标访客的status字段,删除操作自然无效。
解决步骤
给Guest类添加userId字段
在Guest数据类中新增userId: String?字段,存储该访客所属用户的uid,可添加@PropertyName("userId")注解保证和数据库字段名一致。修改监听逻辑,保存访客所属的userId
在SecurityScreen的onDataChange方法中,获取每个访客对应的用户uid并赋值:override fun onDataChange(snapshot: DataSnapshot) { val allGuests = mutableListOf<Guest>() for (userSnapshot in snapshot.children) { val userId = userSnapshot.key // 获取当前用户节点的uid val guestsSnapshot = userSnapshot.child("guests") for (guestSnapshot in guestsSnapshot.children) { val guest = guestSnapshot.getValue(Guest::class.java) guest?.let { it.userId = userId // 给访客绑定所属用户uid allGuests.add(it) } } } guests = allGuests }修正数据库路径,使用访客所属的userId
修改ShareViewModel中的updateStatusInFirebase方法,基于访客的userId构建正确路径,并添加操作结果监听便于排查问题:private fun updateStatusInFirebase(guest: Guest) { val guestUserId = guest.userId if (!guestUserId.isNullOrEmpty() && !guest.id.isNullOrEmpty()) { val database = FirebaseDatabase.getInstance() val guestsRef = database.getReference("users/$guestUserId/guests") guestsRef.child(guest.id).child("status").setValue(null) .addOnCompleteListener { task -> if (task.isSuccessful) { Log.d("DeleteGuestStatus", "Status deleted successfully for guest: ${guest.id}") } else { Log.e("DeleteGuestStatus", "Failed to delete status", task.exception) } } } else { Log.e("DeleteGuestStatus", "Guest's userId or id is null/empty") } }清理冗余代码
deleteGuestStatus方法中it.status = ""是冗余操作,Firebase通过setValue(null)删除字段,若Guest的status是可空类型,可改为it.status = null同步ViewModel数据,否则直接删除该行即可。
内容的提问来源于stack exchange,提问作者Dox
相关产品推荐
相关产品推荐

