Reputation: 236
I am trying to make a hi-score type of tool for my app, so I am playing around with some code and cannot figure out to search through multiple nodes to find the greatest value. The problem seems to be that the DataSnapshot reads the nodes as a HashMap and isn't having problem converting the values to an int. How can I read through the information (player name and player score), have the DataSnapshot identify the greatest value and set the TV to that value?
The code for what I have tried is below. I will also add a screenshot of how my firebase looks to make it visually easier to understand
My WriteToFirebase Activity
public void gFirebase(View view){
int score = (int) (Math.random() * ((50)+1));
Player p1 = new Player();
p1.setName("Player 1");
p1.setScore(score);
DatabaseReference roofRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference gameInfoRef = roofRef.child("hiscore").child("player_name").push();
gameInfoRef.setValue(p1);
}
public void lFirebase(View view){
int score = (int) (Math.random() * ((50)+1));
Player p2 = new Player();
p2.setName("Player 2");
p2.setScore(score);
DatabaseReference roofRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference gameInfoRef = roofRef.child("hiscore").child("player_name").push();
gameInfoRef.setValue(p2);
}
public void sFirebase(View view){
int score = (int) (Math.random() * ((50)+1));
Player p3 = new Player();
p3.setName("Player 3");
p3.setScore(score);
DatabaseReference roofRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference gameInfoRef = roofRef.child("hiscore").child("player_name").push();
gameInfoRef.setValue(p3);
}
My ReadFromFirebase Activity
public void readFromFirebase(View view) {
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference hiscoreRef = rootRef.child("hiscore").child("player_name");
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
int hiscore = 0;
for (DataSnapshot ds : dataSnapshot.getChildren()) {
int value = ds.getValue(Integer.class);
if (hiscore < value) {
hiscore = value;
}
Log.d("TAG", String.valueOf(hiscore));
ChangeMe.setText(hiscore);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
hiscoreRef.addListenerForSingleValueEvent(eventListener);
}
The expected result is for the textview on my screen to change to the highest number in my Firebase system (The highest score)
JSON tree of my database
{
"hiscore" : {
"player_name" : {
"-Lo0W8ks7WCEsrym5Qpl" : {
"name" : "Player 3",
"score" : 24
},
"-Lo0W92WqeUMdq_y7J8M" : {
"name" : "Player 2",
"score" : 42
},
"-Lo0W9KjzXE_XCU4K8MN" : {
"name" : "Player 1",
"score" : 43
}
}
}
}
Upvotes: 0
Views: 68
Reputation: 599946
You can use a Firebase query for this. That will make the server perform the check, instead of having to do this in your own code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference hiscoreRef = rootRef.child("hiscore").child("player_name");
Query hiscoreQuery = hiscoreRef.orderByChild("score").limitToLast(1);
hiscoreQuery.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
int hiscore = 0;
for (DataSnapshot ds: dataSnapshot.getChildren()) {
hiscore = ds.child("score").getValue(Integer.class);
}
Log.d("TAG", String.valueOf(hiscore));
ChangeMe.setText(hiscore);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
You may receive a warning about needing to define an index, in which case you can add this to your Firebase security rules:
"hiscore": {
"player_name": {
".indexOn": "score"
}
}
Upvotes: 1