The following is my Firebase database graph:
There are three children of the root element links. When I execute the following loop to get all children, it returns the result for only the first child
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("links");
int count=0;
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Firebase","Children: "+dataSnapshot.getChildren().toString()); //This gives result for all children
for (DataSnapshot ds : dataSnapshot.getChildren()) {
count++;
}
Log.d("Firebase","Count length: "+count); //Gives only "1"
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
In the above code the count should be 3 but it returns 1. The loop executes only once.
However the following line in the above code works correctly and gives results for all 3 children.
Log.d("Firebase","Children: "+dataSnapshot.getChildren().toString());
Where is the problem? Thanks for your answers!
If you want to get the number of children under links, then try the following:
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Firebase","Children: "+dataSnapshot.getChildren().toString()); //This gives result for all children
long childCount = dataSnapshot.getChildrenCount();
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
getChildrenCount() will return then number of direct children under links, in this case 3.
Related
I want to read Music_ID of the group with Playlist_ID of 2 in firebase.
The following error occurs.
java.lang.NullPointerException: println needs a message
This is my firebase realtime database.
And this is my code.
database = FirebaseDatabase.getInstance();
storage = FirebaseStorage.getInstance();
dref = FirebaseDatabase.getInstance().getReference();
private void Startplaylist(String mood) {
DatabaseReference plist = dref.child("Playlist");
plist.orderByChild("Playlist_ID").equalTo(2).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// Log.i("Value", dataSnapshot.getValue().toString());
String music_id = dataSnapshot.child("Music_ID").getValue(String.class);
Log.i("Value_id", music_id);
str_musictitle.setText(music_id);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
An alarm pops up that an error occurs in this part.
Log.i("Value_id", music_id);
I think "music_id" is not being read.
I tried to change part
String music_id = dataSnapshot.child("Music_ID").getValue(String.class);
to String music_ids = dataSnapshot.child("Music_ID").getValue().toString(); and run it, but I couldn't get the desired result.
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
The code in your onDataChange will need to handle this list by looping over dataSnapshot.getChildren(). Something like this:
DatabaseReference plist = dref.child("Playlist");
plist.orderByChild("Playlist_ID").equalTo(2).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) { // 👈 Loop over results
String music_id = snapshot.child("Music_ID").getValue(String.class); // 👈 Get value for this result
Log.i("Value_id", music_id);
str_musictitle.setText(music_id);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException(); // 👈 Never ignore possible errors
}
});
This is my code. I need to exit from for loop while data snapshot exists or not. I have tried with a listener interface that will invoke a call back when a data snapshot found or not. However, this listener is invoking only after all iterations. I need to exit the loop immediately. I even tried saving a boolean value in a shared preference and retrieve that value and check if it is true then only run for loop. But that approach is also not working. What is happening here, for loop is iterating through all users then only I'm getting the result from firebase background task.
private void createBranchAndAddUser(final String userKey) {
// Getting the referring user from DB
reference.child("User").orderByChild("uid").equalTo(referredBy)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot dst : dataSnapshot.getChildren()) {
referrerKey = dst.getKey(); // Got referring user firebase key
// Getting referring user branches.
reference.child("User").child(referrerKey).child("Branch")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// Branch found under referrer.
if (dataSnapshot.getChildrenCount() == 1) {
// One branch found under referrer. Adding one more under referrer.
Branch branch = new Branch();
branch.setUser_key(userKey);
reference.child("User").child(referrerKey).child("Branch").push().setValue(branch);
} else { // Two branch found under referring user. So moving to the next step.
// GETTING COMPLETE LIST OF USERS WHO ARE REFERRED BY REFERRING USER. (2: Step -> 2)
reference.child("User").orderByChild("referredBy").equalTo(referredBy).
addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// THIS IS THE LOOP I WANT ESCAPE.
for (DataSnapshot ds : dataSnapshot.getChildren()) {
User user = ds.getValue(User.class); // Got all users under referrer.
final String childUserKey = ds.getKey(); // Got firebase key of first child user under referrer.
Log.e(TAG, "isBranch Created " + isBranchCreated);
assert childUserKey != null;
reference.child("User").child(childUserKey).child("Branch")// getting branches of child user. (2: Step -> 3)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
if (dataSnapshot.getChildrenCount() == 1) {
// One branch found under child user.
Branch branch = new Branch();
branch.setUser_key(userKey);
reference.child("User").child(childUserKey).child("Branch").push().setValue(branch);
// need break the loop here, escape from the loop
isBranchCreated = "YES";
}
} else {
Branch branch = new Branch();
branch.setUser_key(userKey);
reference.child("User").child(childUserKey).child("Branch").push().setValue(branch);
// or break the loop here and escape from the loop.
isBranchCreated = "YES";
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.e(TAG, "onCancelled: " + databaseError.getMessage());
}
});
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.e(TAG, "onCancelled: " + databaseError.getMessage());
}
});
}
} else {
// No branch found under referrer.
Branch branch = new Branch();
branch.setUser_key(userKey);
reference.child("User").child(referrerKey).child("Branch").push().setValue(branch);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.e(TAG, "onCancelled: " + databaseError.getMessage());
}
});
}
This question already has answers here:
Firebase Database retrieving sum of multiple childs
(2 answers)
Closed 3 years ago.
Database Structure
I am still new with android and Firebase stuff and I have encountered a few problems when trying to adding the value from node, the thing is, I want to add all value from "price" node, but I have problem where, every price node have different parent, and I don't know how to add all value with different parent
what i've already tried:
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
databaseReference = firebaseDatabase.getReference().child("mycart").child(ID).child(uid).child("quantity");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot dSnapshot : dataSnapshot.getChildren()) {
///...code
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(eventListener);
}
To sum up all your prices from all the keys, you can do this:
databaseReference = firebaseDatabase.getReference().child("mycart").child(ID);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
float price = 0;
for(Datasnapshot snapshot: datasnapshot.getChildren()){
price += snapshot.child("price").getValue(Float.class);
}
Log.d("Total: ", price);
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
I have a list in java android:
List<FirebaseData> GetListMap(String data){
final List<FirebaseData> Elements = new ArrayList<>();
FirebaseDatabase database = FirebaseDatabase.getInstance();
mShiftReference = database.getReference("Map/Data/").child(data);
mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
Elements.add(child.getValue(FirebaseData.class));
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// Failed to read value
Log.w("data", "Failed to read value.", error.toException());
}
});
return Elements;
}
When i try to exctract the size of the array it returns 0, for example:
int size = GetListMap("2019-06-24").size();
Or i can't exctract any property.
Any idea what i'm doing wrong.
First, I assume you mean int size = GetListMap("2019-06-24").size(); (size at the end).
Second, you are assigning a list to the returned value, it's an empty list at this moment. Then you attach a listener that waits for an event (data change), if that happens, then and only then it will add an element to the list.
Basically, your list is always gonna be empty, unless the data change events occur. You need to trigger an event and then check the list, it should change it's size.
You're returning your Elements collection before it actually gets data from your Firebase Database due to the asynchronous nature of your listener.
You'd have to define a callback if you want to get an update after your async code is done
List<FirebaseData> GetListMap(String data){
final List<FirebaseData> Elements = new ArrayList<>();
FirebaseDatabase database = FirebaseDatabase.getInstance();
mShiftReference = database.getReference("Map/Data/").child(data);
mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
System.out.println("About to fill Elements");
for (DataSnapshot child: dataSnapshot.getChildren()) {
Elements.add(child.getValue(FirebaseData.class));
}
System.out.println("Elements is filled");
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// Failed to read value
Log.w("data", "Failed to read value.", error.toException());
}
});
System.out.println("Returning Elements with size: " + Elements.size());
return Elements;
}
int x = GetListMap("...").size();
System.out.println("x: +" x);
``
That code would result in following output:
Returning Elements with size 0
x: 0
About to fill Elements
Elements is filled
Btw please use camelCase for your methods and variables whenever you are developing in Java
You are returning the list before firebase has finished adding everything. You want to create an interface method for the function.
in the class create an interface:
public interface Complete{
void taskCompleted(List<FirebaseData> list);
}
then assign it to your method (now returns void as the interface will be producing the result):
public void GetListMap(String data, Complete completeListener){
. . . .
mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
Elements.add(child.getValue(FirebaseData.class));
}
completeListener.taskComplete(Elements);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
completeListener.taskComplete(null);
}
});
}
To use method:
GetListMap("data", new Complete() {
#Override
public void taskCompleted(List<FirebaseData> list) {
//do what you want with the list object
}
});
First of all your GetListMap method contains firebase database call which of-course asynchronous call. Means you are getting data on separate thread. So the line below this calls execute before firebase process query response. So it is not possible to get returned value from method which contains asynchronous functions.
So to get exact what you want, you will have to wait for query response.
Refer below code to achieve what you want.
// Avoiding return type with this method.
void GetListMap(String data){
final List<FirebaseData> Elements = new ArrayList<>();
FirebaseDatabase database = FirebaseDatabase.getInstance();
mShiftReference = database.getReference("Map/Data/").child(data);
mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
Elements.add(child.getValue(FirebaseData.class));
}
// Use below method to update data inside your views.
// This method will only called once firebase query return response.
updateUI(Elements);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// Failed to read value
Log.w("data", "Failed to read value.", error.toException());
}
});
// Now this method is void so need to return any value.
//return Elements;
}
Example of updateUI(...) method.
void updateUI(List<FirebaseData> elements) {
int size = elements.size();
}
I am trying to store userid's into uidMatches. When I do the first println I am getting the correct string array of matches, but when i do the second one it says my uidMatches array has nothing in it... "[ ]". I don't see how this is possible.
private void populateListView() {
final ArrayList<String> uidMatches = new ArrayList<String>();
final ArrayList<Profile> match_profiles = new ArrayList<Profile>();
users = database.getReference("Users");
user = FirebaseAuth.getInstance().getCurrentUser();
matches = database.getReference("Matches").child(user.getUid());
// Returns uid's for all profiles you matched with
matches.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
String match = child.getValue().toString();
uidMatches.add(match.toString());
System.out.println("HERE ARE MATCHES 1: " + uidMatches);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
System.out.println("HERE ARE MATCHES 2: " + uidMatches);
// Loop to get all Profiles that match each "uidMatches" uid
for (int x=0; x<uidMatches.size(); x++)
{
users.child(uidMatches.get(x)).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren())
{
Profile profile = child.getValue(Profile.class);
match_profiles.add(profile);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
Picture of my firebase setup. I Blocked out the users unique ID's generated from FB login
This isn't a firebase issue it's simply a Java problem. The println at the end of your code gets run when the code first starts when the array is empty. The other println gets fired onDataChange so after the results are populated.