如何优化Firebase实时数据库中用户聊天联系人计数实现?
优化Firebase实时数据库联系人统计方案,降低写入成本
问题现状
当前实现每次发送消息时都会向Contact表写入对方UID,导致大量重复的数据库写入操作,既增加了带宽消耗,也提升了Firebase的使用成本。核心问题在于重复写入已存在的联系人记录。
优化思路
- 仅在首次建立聊天关系时写入联系人:检查当前用户的
Contact节点中是否已存在对方UID,不存在才执行写入 - 合并写入请求:将发送者和接收者的联系人写入合并到一个
updateChildren操作中,减少网络请求次数 - 简化联系人节点结构:无需存储额外字段,直接用对方UID作为节点键,通过节点存在性判断是否为联系人
修改后的核心代码
发送消息方法优化
ContactRef = FirebaseDatabase.getInstance().getReference().child("Contact"); private void SendMessage() { DatabaseReference reference = FirebaseDatabase.getInstance().getReference(); final String messageText = messageınputtext.getText().toString(); if (TextUtils.isEmpty(messageText)){ return; } String messagesenderref ="message/" + messageSenderID + "/" + messageReceiverID; String messagereceiverref ="message/" + messageReceiverID + "/" + messageSenderID; DatabaseReference usermessagekeyref = Rootref.child("message") .child(messageSenderID).child(messageReceiverID).push(); String messagepushid = usermessagekeyref.getKey(); Map messageTextBody = new HashMap(); messageTextBody.put("message" , messageText); messageTextBody.put("time" , saveCurrentTime); messageTextBody.put("date" , saveCurrentDate); messageTextBody.put("type" , "text"); messageTextBody.put("from" , messageSenderID); Map messageBodyDetails = new HashMap(); messageBodyDetails.put(messagesenderref + "/" + messagepushid , messageTextBody); messageBodyDetails.put(messagereceiverref + "/" + messagepushid , messageTextBody); Rootref.updateChildren(messageBodyDetails).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (!task.isSuccessful()){ String message = task.getException().getMessage(); Toast.makeText(context, "Error :" + message , Toast.LENGTH_SHORT).show(); } } }); // 检查是否已存在联系人记录,不存在才写入 ContactRef.child(messageSenderID).child(messageReceiverID).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { if (!dataSnapshot.exists()) { // 合并发送者和接收者的联系人写入操作 Map contactUpdates = new HashMap(); contactUpdates.put(messageSenderID + "/" + messageReceiverID, true); contactUpdates.put(messageReceiverID + "/" + messageSenderID, true); ContactRef.updateChildren(contactUpdates); } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { // 处理取消事件 } }); }
联系人计数代码优化
// 修正:指向当前用户的Contact节点,统计自身联系人数量 ContactRef.child(messageSenderID).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { countusercontact = (int) dataSnapshot.getChildrenCount(); contactcount.setText(Integer.toString(countusercontact)); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { // 处理取消事件 } });
优化说明
- 避免重复写入:通过
dataSnapshot.exists()判断对方是否已在联系人列表中,仅首次聊天时执行写入操作 - 减少请求次数:用一个
updateChildren同时完成双方的联系人记录写入,将两次请求合并为一次 - 简化数据结构:用
true作为节点值(或直接省略值,仅利用节点存在性),减少存储冗余 - 计数逻辑修正:原代码错误统计了根节点下的所有用户,优化后只统计当前用户的子节点数量,符合实际需求
数据库结构说明
优化后的Contact节点结构如下(与原截图结构兼容,仅减少重复写入):
Contact ├─ 用户AUID │ ├─ 用户BUID: true │ └─ 用户CUID: true └─ 用户BUID └─ 用户AUID: true
内容的提问来源于stack exchange,提问作者Muratcan Yıldız
相关产品推荐
相关产品推荐

