如何检测两位用户同时打开聊天?Firebase代码功能异常排查
Your current approach has a critical flaw: using a single chat opened boolean field can’t track the state of two separate users. When one user sets it to true and the other interacts with the field, you end up overwriting values incorrectly, leading to the false state you’re seeing. Here’s how to fix this properly:
The Core Issue
A single boolean can only represent one state (open/closed), but you need to track each user’s individual presence in the chat. Instead of a single field, use a map to store each user’s active status independently.
Step 1: Update Your Data Structure
Replace the chat opened field with a activeUsers map. This map will have user IDs as keys and boolean values indicating whether that user has the chat open. For example:
{ "activeUsers": { "userID1": true, "userID2": false } }
Step 2: Set User State When Opening/Closing the Chat
When the current user opens the chat, set their entry in the activeUsers map to true. When they close it, set it to false:
Opening the Chat
// Call this when the user opens the chat screen firebaseFirestore.collection(getString(R.string.app_name)) .document("App Collections") .collection("Users") .document(contactID) .collection("Chats With") .document(userID) .update("activeUsers." + userID, true);
Closing the Chat
// Call this when the user closes the chat screen (e.g., onDestroy) firebaseFirestore.collection(getString(R.string.app_name)) .document("App Collections") .collection("Users") .document(contactID) .collection("Chats With") .document(userID) .update("activeUsers." + userID, false);
Step 3: Listen for Both Users’ States
Modify your snapshot listener to check if both users have their activeUsers entries set to true:
firebaseFirestore.collection(getString(R.string.app_name)) .document("App Collections") .collection("Users") .document(contactID) .collection("Chats With") .document(userID) .addSnapshotListener(new EventListener<DocumentSnapshot>() { @Override public void onEvent(@Nullable DocumentSnapshot documentSnapshot, @Nullable FirebaseFirestoreException e) { // Handle errors or missing documents if (e != null || documentSnapshot == null || !documentSnapshot.exists()) { Log.e("ChatState", "Error fetching chat state: " + (e != null ? e.getMessage() : "No document found")); return; } // Get the activeUsers map (default to empty if missing) Map<String, Boolean> activeUsers = (Map<String, Boolean>) documentSnapshot.getOrDefault("activeUsers", new HashMap<>()); // Check if both users are active boolean currentUserIsActive = activeUsers.getOrDefault(userID, false); boolean contactIsActive = activeUsers.getOrDefault(contactID, false); boolean bothUsersAreInChat = currentUserIsActive && contactIsActive; // Use the result as needed if (bothUsersAreInChat) { // Both users have the chat open - do something (e.g., show "online" indicator) Log.d("ChatState", "Both users are in the chat!"); } else { // At least one user has closed the chat Log.d("ChatState", "One or both users have left the chat"); } } });
Key Notes
- Avoid Redundant Writes: Your original listener was writing the same value back to Firestore, which served no purpose and could cause race conditions. The updated listener only reads state, not modifies it.
- Initialize the Document: If the
Chats Withdocument doesn’t exist yet, Firestore will automatically create it when you callupdate()with theactiveUsersmap. - Handle Cleanup: Make sure to set the user’s state to
falsewhen they navigate away from the chat (e.g., inonPause()oronDestroy()of your activity/fragment) to avoid false "active" statuses.
内容的提问来源于stack exchange,提问作者fsdklfm

