Firebase keeps changing the value and adding new child - java

I am trying to load data from firebase database and then I want to add some more data to it and in the end I want it to upload back. But the problem is when the data is being uploaded back it is not stopping after updating the data. It looks like it is under loop and doing the task again and again.
mTempDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChild(mAuth.getCurrentUser().getUid())){
final DatabaseReference newTemp = mTempDatabase.child(mAuth.getCurrentUser().getUid());
final long qntCount = (long) dataSnapshot.child(mAuth.getCurrentUser().getUid()).child("QuantityCount").getValue();
final long foodamount = (long) dataSnapshot.child(mAuth.getCurrentUser().getUid()).child("QuantityCount").getValue();
//final long countfood = (long) dataSnapshot.child(mAuth.getCurrentUser().getUid()).child("QuantityCount").getValue();
mDatabaseBestseller.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String foodname = (String) dataSnapshot.child(food_key).child("foodname").getValue();
long foodprice = (long) dataSnapshot.child(food_key).child("foodprice").getValue();
long mfoodprice = foodprice + foodamount;
long mqntCOunt = qntCount +1;
newTemp.child("QuantityCount").setValue(mqntCOunt);
newTemp.child("FoodPrice1").setValue(mfoodprice);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mTempDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.hasChild(mAuth.getCurrentUser().getUid())) {
final DatabaseReference newTemp = mTempDatabase.child(mAuth.getCurrentUser().getUid());
mDatabaseBestseller.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String foodname = (String) dataSnapshot.child(food_key).child("foodname").getValue();
long foodprice = (long) dataSnapshot.child(food_key).child("foodprice").getValue();
newTemp.child("QuantityCount").setValue(1);
newTemp.child("CountFood1").setValue(1);
newTemp.child("Food1").setValue(foodname);
newTemp.child("FoodPrice1").setValue(foodprice);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
viewHolder.mFoodAddLayout.setVisibility(View.INVISIBLE);
viewHolder.mIncrLayout.setVisibility(View.VISIBLE);
}
});
According to my understanding I have did wrong math while retrieving the data and adding the data back.

addValueEventListener() will always listening to database reference value changes.if you want to stop listening you have to use removeEventListener(valueListener),
But addListenerForSingleValueEvent() executes onDataChange method immediately and after executing that method once, it stops listening to value changes.

You need to use the .addListenerForSingleValueEvent() instead of .addValueEventListener(). The difference is, the second one keep updating every time a value is changed in the database, which keep happening as you update your value inside the function. But, the first method that I am suggesting, just read the values once, which is what you need here.

Related

Firebase: modify/update string number

So im trying every time a button is clicked to update the value of the itemcategory child which is a string number in firebase, by adding 1 to this value. Please dont suggest me to convert this string to integer by removing "". It is very important for me to be a string.
My Firebase structure:
This is my code
final DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("Items").child(ID).child("itemcategory");
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//how to get the current value of itemcategory field?
//how to modify it and add +1 to this string number?
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Im coping with this 3 weeks and havent find any solution.
As i wrote in the comments i have 2 questions:
how to get the current value of itemcategory field?
how to modify it and add +1 to this string number?
If you're updating a node based on its current value, consider using a transaction for this. Without a transaction you run the risk that multiple users end up overwriting each others values.
In your code it'd look something like:
final DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("Items").child(ID).child("itemcategory");
postRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
String value = mutableData.getValue(String.class);
int number;
if (string == null) {
number = 0;
}
else {
number = Integer.parseInt(value);
}
number = number + 1
mutableData.setValue(String.valueOf(number));
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean committed,
DataSnapshot currentData) {
Log.d(TAG, "Transaction:onComplete:" + databaseError);
}
});
This way retrieve the value convert it to integer then add it and store as string.
final DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("Items").child(ID);
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String number = dataSnapshot.child("itemcategory").getValue(String.class);
int value = Integer.parseInt(number);
int newValue = value + 1;
mDatabase.child("itemcategory").setValue(String.valueOf(newValue));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

how to get specific nodes under unique keys in firebase realtime database android

I am trying to get data from nested nodes under unique keys. Each key is identical. It's difficult for me to deal with such problem help please.
I have tried ChildEventListener on database reference but not succeeded.
here is the code i am using to retreive data
InfoFragment.java
auth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance().getReference("Seller").getRef().child("ImpInfo");
mFirebaseDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postDataSnapshot : dataSnapshot.getChildren()) {
ShopSellerInfo shopSellerInfo = postDataSnapshot.getValue(ShopSellerInfo.class);
mShopSellerInfo.add(shopSellerInfo);
}
mNearBySellerAdapter = new NearBySellerAdapter(getContext(), mShopSellerInfo);
mRecyclerView.setAdapter(mNearBySellerAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return rootView;`
ShopSellerInfo.java
public ShopSellerInfo(String shopAddress, String shopPhoneNo, String
shopImageUrl, String shopName) {
this.shopAddress = shopAddress;
this.shopPhoneNo = shopPhoneNo;
this.shopImageUrl = shopImageUrl;
this.shopName = shopName;
}
public ShopSellerInfo() {
}
public String getShopAddress() {
return shopAddress;
}
public String getShopPhoneNo() {
return shopPhoneNo;
}
public String getShopImageUrl() {
return shopImageUrl;
}
public String getShopName() {
return shopName;
}
public void setUserAddress(String shopAddress) {
this.shopAddress = shopAddress;
}
public void setUserPhoneNo(String shopPhoneNo) {
this.shopPhoneNo = shopPhoneNo;
}
public void setImageUrl(String shopImageUrl) {
this.shopImageUrl = shopImageUrl;
}
public void setShopName(String shopName) {
this.shopName = shopName;
}
}
This is the structure of my Database
I have a specific node in each unique key the contain data. I want to retrieve that data form every child node and show on single activity.
You're not too far off, just a few mistakes. The following is closer to what you need:
mFirebaseDatabase = FirebaseDatabase.getInstance().getReference("Seller");
mFirebaseDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot sellerSnapshot : dataSnapshot.getChildren()) {
DataSnapshot impInfoSnapshot = sellerSnapshot.child("ImpInfo");
ShopSellerInfo shopSellerInfo = impInfoSnapshot.getValue(ShopSellerInfo.class);
mShopSellerInfo.add(shopSellerInfo);
mNearBySellerAdapter = new NearBySellerAdapter(getContext(), mShopSellerInfo);
mRecyclerView.setAdapter(mNearBySellerAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
Changes:
Removed the call to .getRef(), which is not needed and in general an anti-pattern.
Removed the call to .child("ImpInfo") from the DatabaseReference, since there is no /Seller/ImpInfo.
Added .child("ImpInfo") in the loop, since you want the ImpInfo child of each snapshot.
Raise an error if onCancelled triggers, since it's a bad practice to ignore errors.

Retrieve the children of a parent node and perform a method on each value

I am building an app that needs to retrieve all child from a certain parent node and would like to perform a method call on each child retrieved.
Here is my current database:
Click Me
I would like to call all child of conradjr and on retrieval of a child for example "ranniecardino15", it should store it to a variable then perform a method call. How can I do this?
I have made a code like this but the method call "getCurrentLocation" is only performed on the last child retrieved.
public void getCurrentChildUser() {
DatabaseReference getuser = FirebaseDatabase.getInstance().getReference().child("Children");
getuser.child(user).orderByChild("CurrentLocation").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
childuser = childSnapshot.getKey();
if (childuser != null){
getCurrentLocation();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public void getCurrentLocation(){
DatabaseReference getuser = FirebaseDatabase.getInstance().getReference().child("Children");
getuser.child(user).child(childuser).child("CurrentLocation").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot != null){
currentloc = dataSnapshot.getValue(String.class);
System.out.println("Current Location: "+currentloc);
String split[] = currentloc.split(",");
lat1 = Double.parseDouble(split[0]);
lng1 = Double.parseDouble(split[1]);
System.out.println("Current Latitude: "+lat1+" and Current Longitude: "+lng1);
getSavedLocation();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
Please help me :) Thanks in advance :)
To solve this, you need to change the declaration of your getCurrentLocation() method from:
public void getCurrentLocation(){}
to
public void getCurrentLocation(String childuser){}
Now you need to call this method from inside the onDataChange() method like this:
getCurrentLocation(childuser);
See, I have passed the childuser as an argument to the getCurrentLocation() so it can be used in a proper way.

Getting list of items/children from Firebase Database?

I'm running into some trouble figuring out how to get the number of items/children in my Firebase real-time database for my app to use as an int value.
Check the image below:
So as you can see above, I have 2 children of images_list.
What I want to do is: get the number of items/children of images_list returned to my app, which would obviously equal 2 initially, and have this number expand whenever I add more items/children.
So my question is, what code do I implement to grab the number of children in this database? And how could I then convert this number into an int value? I've already experimented with differing methods, but I haven't found a solution as of yet.
I hope that made sense. Thanks so much for any of your assistance!
Code solution down here; I had to move most of this code from my RecyclerView Adapter into my MainActivity for it to work
Interface
public interface FirebaseCallback {
void onCallback(List<String> list);
}
readData method
private void readData(final FirebaseCallback firebaseCallback) {
mDatabaseImagesRef = FirebaseDatabase.getInstance().getReference("images_list");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String imageItems = ds.getValue(String.class);
imageList.add(imageItems);
}
firebaseCallback.onCallback(imageList);
Log.i("imageList.size() is: ", String.valueOf(imageList.size()));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.i(LOG_TAG, databaseError.getMessage());
}
};
mDatabaseImagesRef.addListenerForSingleValueEvent(valueEventListener);
}
called in onCreate()
readData(new FirebaseCallback() {
#Override
public void onCallback(List<String> list) {
mImageAdapter.notifyDataSetChanged();
}
});
getItemCount() in RecyclerViewAdapter
#Override
public int getItemCount() {
return imagesList.size();
}
To count the all the children beneath images_list node, please use the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference imagesListRef = rootRef.child("images_list");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int count = (int) dataSnapshot.getChildrenCount(); //Cast long to int
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
imagesListRef.addListenerForSingleValueEvent(valueEventListener);
how could I then convert this number into an int value?
According to the official documentation, getChildrenCount() method returns a long and not an int. So you need to cast that primitive long to an int.
how to extract count from this block of code so that it can be referenced and used outside this code as well?
You cannot simply create the count variable as a global variable and use it outside the onDataChange() method because it will always be 0 due the asynchronous behaviour of this method. This means that if try to use its result outside this method, the data hasn't finished loading yet from the database and that's why is not accessible. With other words, your count will always be 0.
A quick solve for this problem would be to use the value of your count variable only inside the onDataChange() method, otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.
try this
userReference = FirebaseDatabase.getInstance().getReference("images_list");
userReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
num = dataSnapshot.getChildrenCount();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mRef= FirebaseDatabase.getInstance().getReference("images_list");
on your "onDataChange" method inside the listener , use getChildrenCount() to get the number of images, you can iterate those children using i loop , Exmeple :
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int count = dataSnapshot.getChildrenCount();
// here you get your images number
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String key = ds.getKey()
// and here you get the key
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Try this code:
public void onDataChange(#NonNull DataSnapshot snap) {
int count = (int) snap.getChildrenCount();
//shows the number of items
}

Comparing data from Firebase

Hi guys well I'm getting a null and i dont know why.. i'll apreciate if u can help me.
this is my json on Firebase.
usuarios{
krum{
dni: "43193622"
email: "pedroccc"
login: "krum"
nombre:"pedro"
pass: "1234" }
and this is my method:
login_text = (EditText) findViewById(R.id.txtLogin);
onClickListener:
final String log_child = login_text.getText().toString();
final String pass_child = pass_text.getText().toString();
mDatabase = FirebaseDatabase.getInstance().getReference("usuarios").child(log_child);
mDatabase.child("pass").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String mpass = dataSnapshot.getValue(String.class);
pass = mpass;
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
then i compare pass with pass_child with equals and i getting that pass is null.. any idea? thank you
PD. In Firebase all settings are true
Try this:
final String log_child = login_text.getText().toString();
final String pass_child = pass_text.getText().toString();
mDatabase = FirebaseDatabase.getInstance().getReference("usuarios").child(log_child);
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot data : dataSnapshot.getChildren()){
String mpass = data.getValue().toString();
pass = mpass;
if(pass.equals(pass_child)){
//code here
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Adding the for loop will enable you to get the pass from the database. Since onDatachange is asynchronous(means it does not wait until it finishes retrieving data, and it goes to other methods after it, then when it retrieves the data it comes back to the method onDatachange) then you have to compare inside the method onDatachange

Categories