I need to count all the children that are in my Firebase database.
This is the Firebase structure:
Level 1
- CHILD1
- - subchild1
- - subchild2
- CHILD2
- - subchild 1
How can I count the CHILDs from level 1?
(In this example it would need to return 2...)
Query the first level and then in your SnapShot, use : getChildrenCount().
So the query will be something like this:
myRef.child("level1").child("subchild1"). // Your listener after
Check this link.
And here.
Try This
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference ref = db.getReference();
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.e(dataSnapshot.getKey(),dataSnapshot.getChildrenCount() + "");
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
DatabaseReference mDatabaseRef = FirebaseDatabase.getInstance().getReference();
mDatabaseRef.child("level1").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long count= dataSnapshot.getChildrenCount();
}
});
This code will help you .
(int)dataSnapshot.getChildrenCount()
Related
// This is the MainActivity, I have used firebase to store sample data, where I can update and retrieve.
But retrieval of data is possible only when there is a data change,but I want to see my data which is in firebase already
here is the data base structure]1
public class MainActivity extends
AppCompatActivity {
EditText name,weight;
Button uploadBtn;
TextView itemName,itemWeight;
DatabaseReference databaseReference=FirebaseDatabase.getInstance().getReference();
Map<String,String>values=new HashMap<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name=findViewById(R.id.inputItemName);
weight=findViewById(R.id.inputItemWeight);
uploadBtn=findViewById(R.id.uploadButton);
itemName=findViewById(R.id.resultName);
itemWeight=findViewById(R.id.resultWeight);
// Here as you can see I have used an ValueEventListener to show the retrieve values from database before uploading the new Values But it is not working , unless the values of data are changed (that is it works only after uploading new values).
ValueEventListener valueEventListener=new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String nameD=(String) dataSnapshot.child("Name").getValue();
String weightD = (String) dataSnapshot.child("Weight").getValue();
itemName.setText(nameD);
itemWeight.setText(weightD+" Kg");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
databaseReference.addListenerForSingleValueEvent(valueEventListener);
uploadBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
values.put("Name",name.getText().toString());
values.put("Weight",weight.getText().toString());
databaseReference.child("UToouch").setValue(values);
}
});
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
String nameDb=(String) dataSnapshot.child("Name").getValue();
String weightDb = (String) dataSnapshot.child("Weight").getValue();
itemName.setText(nameDb);
itemWeight.setText(weightDb+" Kg");
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
To be able to get values of your Name and Weight properties, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child("UToouch");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("Name").getValue(String.class);
String weight = dataSnapshot.child("Weight").getValue(String.class);
Log.d(TAG, name + " / " + weight);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
ref.addListenerForSingleValueEvent(valueEventListener);
The output in your logcat will be:
rittesh / pv
Im creating an app with Firebase database here is my data structure:
{
"teachers" : {
"USYSacnOjDR5EAPwljZMHtggN9I2" : {
"name" : {
"teacher_name" : "Alison"
},
"members": {
"sIrfMA3bm0R9uj55nDUFpFyabcL2" : true
}
}
},
"users" : {
"sIrfMA3bm0R9uj55nDUFpFyabcL2" : {
"position" : {
"bpos" : "0"
},
"name" : {
"email" : "m#m.com",
"name" : "John",
"surname" : "Clash"
}
}
So now in RecyclerView im trying to display all of the Alison teacher members, as you can see John Clash is set to true. Anyway when i try to retrieve user this way:
reference = FirebaseDatabase.getInstance().getReference("teachers").child(teacherkey).child("members");
reference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
User user = dataSnapshot.child("name").getValue(User.class);
result.add(user);
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
User user = dataSnapshot.child("name").getValue(User.class);
result.remove(user);
adapter.notifyDataSetChanged();
}
the app crash because of NPE, datasnapshot key is valid, it is John's account key but value of snapshot is true. How can i solve that and get from John's data name and surname?
#Edit:
Here is my retrieving code:
public void updateList() {
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String userId = ds.getKey();
DatabaseReference userIdRef = FirebaseDatabase.getInstance().getReference().child("users").child(userId);
userIdRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
User user = dataSnapshot.child("name").getValue(User.class);
result.add(user);
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
To solve this, you need to query your database twice. Please see the code below:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference membersRef = rootRef.child(teachers).child(teacherId).child("members");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String userId = ds.key();
DatabaseReference userIdRef = rootRef.child("users").child(userId);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
Log.d("TAG", user.getName());
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
userIdRef.addListenerForSingleValueEvent(eventListener);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
membersRef.addListenerForSingleValueEvent(valueEventListener);
You have 2 approaches to solve this issue:
a.) Inside onChildAdded you already have, if the value you got is true, do another search in database, but this time in "users" node. Something like
newReference = FirebaseDatabase.getInstance().getReference("users").child(dataSnapshot.getKey).child("name")
b.) In the "members" node, write "John Clash" instead of "true". This approach will work for now, but you will fall into the first approach if someday you need to retrieve email address as well
public void getFirstName(View view) {
Query newQuery = database.getReference("users").orderByChild("firstName");
newQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Iterable<DataSnapshot> iterator = dataSnapshot.getChildren();
for (DataSnapshot child : iterator) {
Friends friends = child.getValue(Friends.class);
Toast.makeText(DBActivity.this, friends.firstName, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I am trying to retrieve the first names of all friends. When I try the above code for the mentioned JSON file structure, I am getting this error "Can't convert object of type java.lang.String to type com.example.seth.photopicker.Friends". Please help me with this issue.
Try this:
Query newQuery = database.getReference("users");
newQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String fname=dataSnapshot.child("firstName").getValue().toString();
Toast.makeText(DBActivity.this, friends.firstName, Toast.LENGTH_SHORT).show();
}
}
The datasnapshot is at users and since you are using onChildAdded you do not need to iterate to be able to get the first name.
Query newQuery = database.getReference("users").orderByChild("firstName");
newQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Friends friends = dataSnapshot1.getValue(Friends.class);
Toast.makeText(DBActivity.this, friends.firstName, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Equivalent code for above answer without using Child Listener.
I've created AutoCompleteTextView for Ingredient, it works perfect. The DB save also works, I've tested it without validation.
If Ingredient exists in Firebase db I want to add recipe to DB.
For example if RecipeIngredients="milk" recipe should be saved to DB.
Here's my code.
DatabaseReference ingDBref = FirebaseDatabase.getInstance().getReference("Ingredients");
DatabaseReference databaseReference=FirebaseDatabase.getInstance().getReference("Recipes");
public void addRecipe(){
final String RecipeName=RecipeNameEditText.getText().toString();
final String RecipePrepareTime=PrepareTimeEditText.getText().toString();
final String RecipeIngredients=IngredientsACTV.getText().toString();
final String RecipeDescription=DescriptionEditText.getText().toString();
final String RecipeDifficulty=DifficultySpinner.getSelectedItem().toString();
key=databaseReference.push().getKey();
ingDBref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot data: dataSnapshot.getChildren()){
if(data.child(RecipeIngredients).getValue()!=null){
Recipes recipes=new Recipes(key,RecipeName,RecipeDifficulty,RecipePrepareTime,RecipeIngredients,RecipeDescription);
databaseReference.child(key).setValue(recipes);
Toast.makeText(AddRecipeActivity.this,"Saved...",Toast.LENGTH_LONG).show();
}
else{
IngredientsACTV.setText("");
Toast.makeText(AddRecipeActivity.this,"Error...",Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Firebase DB
if(data.child("ingredientName").getValue().equals(RecipeIngredients))
Solved my problem.
This is happening because you are looping through the whole object. If the condition has been met, then you you set that value, if not then the else part is triggered for each of the remaining elements.
To solve this you can remove the else part if not needed or you need to use the exists() method provided by Firebase. To achieve this, just attach a listener on the same database reference and check if that child exists.
Hope it helps.
Try this
mDatabase.child("Ingredients")
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map<String, String> map = (Map<String, String>) dataSnapshot.getValue();
String value=map.get("IngredientName");
// here will be your value of IngredientName
if(value.equals("Milk"){
// do something
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
myDialog.CancelProgressDialog();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
myDialog.CancelProgressDialog();
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
myDialog.CancelProgressDialog();
}
#Override
public void onCancelled(DatabaseError databaseError) {
myDialog.CancelProgressDialog();
}
});
Please how do I simply get the child count from a firebase Query. For example Let's say I use a database query with 10 children, how do I get that value because I tried using onChildChanged and getting the value from the snapshot, but it does not work well. This is because at first it will get the number, then it will query again because it has to continuously sync, but because there is not actual child change at the second query it return a value if zero which will replace the original correct value. :/
databaseReference.child("PrinterView").child(uni).child(phone).orderByChild("done").equalTo("No").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Toast.makeText(getActivity(),"Number:"+String.valueOf(dataSnapshot.getChildrenCount()),Toast.LENGTH_LONG).show();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Both don't work
databaseReference.child("PrinterView").child(uni).child(phone).orderByChild("done").equalTo("No").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Toast.makeText(getActivity(),"Number:"+String.valueOf(dataSnapshot.getChildrenCount()),Toast.LENGTH_LONG).show();
Vendor_view_Home_fragment.printIndicator.setText(String.valueOf(dataSnapshot.getChildrenCount()));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Assuming that PrinterView is a direct child of your Firebase root, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference yourRef = rootRef.child("PrinterView").child("Covenant University").child("588");
Query query = yourRef.orderByChild("done").equalTo("No");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long count = dataSnapshot.getChildrenCount();
Log.d("TAG", String.valueOf(count));
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
query.addListenerForSingleValueEvent(eventListener);
The problem was this line:
databaseReference.child("PrinterView").child(uni).child(phone).orderByChild("done").equalTo("No").addValueEventListener(new ValueEventListener()
The variable "uni" and "phone" was also provided by a firebase Query E.G It was to get the University and phone number of the current user so I could not just put a static string there.
databaseReference.child("Users").child(mAuth.getCurrentUser().getUid()).child("Phone").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
phone = dataSnapshot.getValue().toString();
// Toast.makeText(getActivity(), phone, Toast.LENGTH_LONG).show();
setPendingList();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
So the issue was that, if the network connection was slow or if the queries were not done yet, those two variables would be empty thereby making the dataSnapshot empty. I will have to sort that out by only allowing that to be queried when the rest are sure to be done. :)