Android Firebase从未知键获取子节点并映射至heartScore对象的方法
heartScore Objects Got it, let's break down how to solve this. You're working with a Firebase Realtime Database structure where each user has timestamped quiz entries, and you want to pull those entries (even though the timestamp keys are unknown upfront) and convert them into your custom heartScore objects. Here's how to implement this across common platforms:
Android (Java)
First, make sure your heartScore class meets Firebase's requirements for object mapping:
- It has a no-argument constructor
- Member variable names match the database keys exactly (or use
@PropertyNameannotations if you prefer camelCase in code, e.g.,@PropertyName("exercise_total") private String exerciseTotal;) - Optional: Add a
timestampfield to store the key of each entry
Here's the code to fetch and map the data:
// Get reference to the specific user's quiz entries DatabaseReference userQuizRef = FirebaseDatabase.getInstance() .getReference("users") // Adjust this to your root node name if needed .child("-EvcKZHBZ4CVo9yAdlP7ldadCZS03"); // Listen for changes (or use get() for one-time fetch) userQuizRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { List<heartScore> userQuizEntries = new ArrayList<>(); // Iterate through all timestamped child nodes for (DataSnapshot timestampSnapshot : dataSnapshot.getChildren()) { // Map the snapshot directly to your heartScore object heartScore score = timestampSnapshot.getValue(heartScore.class); // If you want to keep the timestamp, assign the node's key to your object if (score != null) { score.setTimestamp(timestampSnapshot.getKey()); userQuizEntries.add(score); } } // Now you have a list of all heartScore objects for the user // Use this list as needed (display, process, etc.) } @Override public void onCancelled(DatabaseError databaseError) { // Handle errors (log, show user message, etc.) Log.e("FirebaseData", "Failed to fetch quiz entries", databaseError.toException()); } });
Android (Kotlin)
Similar to Java, ensure your heartScore class has a no-arg constructor (or use data class with default values) and matches the database key names.
val userQuizRef = FirebaseDatabase.getInstance() .getReference("users") .child("-EvcKZHBZ4CVo9yAdlP7ldadCZS03") userQuizRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { val userQuizEntries = mutableListOf<heartScore>() dataSnapshot.children.forEach { timestampSnapshot -> val score = timestampSnapshot.getValue(heartScore::class.java) score?.let { it.timestamp = timestampSnapshot.key userQuizEntries.add(it) } } // Process the list of heartScore objects } override fun onCancelled(databaseError: DatabaseError) { Log.e("FirebaseData", "Failed to fetch quiz entries", databaseError.toException()) } })
iOS (Swift)
For Swift, make sure your heartScore struct/class conforms to Codable (Firebase supports Codable out of the box). Add an optional timestamp property if you want to store the entry's timestamp key.
import FirebaseDatabase struct heartScore: Codable { var age: String var exercise_total: String // Add all other matching properties here var timestamp: String? // Optional, to store the timestamp key } // Fetch the user's quiz entries let userQuizRef = Database.database().reference() .child("users") .child("-EvcKZHBZ4CVo9yAdlP7ldadCZS03") userQuizRef.observe(.value) { snapshot in var userQuizEntries = [heartScore]() for child in snapshot.children { guard let timestampSnapshot = child as? DataSnapshot else { continue } // Map the snapshot data to heartScore do { var score = try timestampSnapshot.data(as: heartScore.self) score.timestamp = timestampSnapshot.key userQuizEntries.append(score) } catch { print("Failed to map entry: \(error.localizedDescription)") } } // Use the userQuizEntries list as needed } withCancel: { error in print("Failed to fetch data: \(error.localizedDescription)") }
Key Notes
- Field Matching: Ensure your
heartScoreproperties exactly match the database keys (case-sensitive!). If you prefer different naming in code, use annotations (Java/Kotlin) orCodingKeys(Swift) to map them. - Data Types: Keep the data types consistent between your database and
heartScoreclass. For example, if the database storesageas a string ("20"), yourheartScoreshould have aStringproperty forage(or convert it manually after mapping). - One-Time vs Real-Time: Use
addValueEventListenerfor real-time updates, orget()(Java/Kotlin) /getData()(Swift) if you only need to fetch the data once.
内容的提问来源于stack exchange,提问作者jlevis73

