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) {
}
});
Related
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
}
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.
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
cBankRef=myRef.child("user_id").child("ASSETS");
cBankRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.child("1").child("description").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is"+value);
if(dataSnapshot.child("2").exists()) {
String valuess = dataSnapshot.child("3").child("description").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is: " + valuess);
}
if (dataSnapshot.child("3").exists()) {
String values = dataSnapshot.child("1").child("description").getValue(String.class);
Log.d(TAG, "onChildAdded: the cash at bank is: "+values);
}
}
#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) {
}
});
first i accessed the user_id child and the ASSETS then through the nodes ("1"),("2") i had to add other nodes in order to get the value, the("1") and ("2") were ("Cash at Bank") ("stock") in the beginning but i decided to change them to numbers but it's giving null #makrand pawar
You have multiple issues in your example:
Your cBankRef is pointing to \user_id\ASSETS\Cash at bank\stock\Cash in Hand, which does not exist (Cash at bank node does not exist under ASSETS).
You are then attaching a ChildEventListener to this reference, which won't return any values, because there aren't any children under it (as it doesn't exist).
Inside onChildAdded(), you are trying to access the houses node which also doesn't exist in your example (house does though).
To access the children under the Stock node, you'll need something like:
ref = FirebaseDatabase.getInstance().getReference().child("user_id").child("ASSETS").child("Stock");
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.child("house").child("values").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is: "+value);
}
// ...
});
The DatabaseReference#child() method is not a SELECT statement. To access everything underneath a node, you only need to create a reference to the highest node required, then attach a listener to that.
For example, if you need access to everything underneath the ASSETS node, you could attach a listener there instead:
ref = FirebaseDatabase.getInstance().getReference().child("user_id").child("ASSETS");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.child("Stock").child("house").child("values").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is: "+value);
if (dataSnapshot.child("Cash at bank").exists()) {
String value = dataSnapshot.child("Cash at bank").getValue(String.class);
Log.d(TAG, "onChildAdded: the cash at bank is: "+value);
}
}
// ...
});
Then when the listener returns you can use DataSnapshot#child() instead to access the individual values retrieved from that location. Also, using DataSnapshot#exists() is a simple way to check that a node exists before using it.
If you plan to have additional values or nodes under ASSETS that don't currently exist, they will be returned by the above listener as soon as they are created.
To achieve this, i suggest you using ValueEventListener like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference stockRef = rootRef.child("user_id").child("ASSETS").child("Stock");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String values = ds.child("house").child("values").getValue(String.class);
Log.d("TAG", values);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
stockRef.addListenerForSingleValueEvent(eventListener);
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.