How to update data using firebase transaction? - java

I am facing a problem of how to exactly use Firebase Transaction runTransaction() method. Here when the user clicks the button I am trying to fetch the value from database and increment it and then again send it back to database. Now issue is what if multiple users tap the button at the same time, for this I am using Firebase transaction. But don't know exactly how to write the code. Here is the code which I have tried but not working. I just want to update the value from 0 to 1, if button is clicked by only one user and if clicked simultaneously by many users, then one of the user should wait until the first user completes the updating.
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
final String mainValue = (String) dataSnapshot.child("values").child("number").getValue();
btnInc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
myRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(final MutableData mutableData) {
mutableData.child("number").setValue(String.valueOf(Integer.parseInt(mainValue) + 1));
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
Toast.makeText(MainActivity.this, "Result: "+b, Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, "Error: "+databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Here is my database screenshot

Related

Why is the method of receiving data from firebase not working?

I registered such a method of receiving from folders in firebase, first I tried it in SwipeCard, it didn’t appear there, so I did the same test in a simple imageview and the data didn’t appear either. The link opens the photo. What is wrong in my code change and how to fix it? Thanks in advance
private void getUsermenwomInfo()
{
DatabaseReference reference= FirebaseDatabase.getInstance().getReference()
.child("User");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()&&snapshot.getChildrenCount()>0)
{
String name=snapshot.child("name").getValue().toString();
nameusercard.setText(name);
if (snapshot.hasChild("image")) {
String image = snapshot.child("image").getValue().toString();
Picasso.get().load(image).into(imageosnovnoe);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
}

Get a specific nested child and count it

I making an Attendance App.
In the app there is a function to know how many event an users already attend and what event they attend.
What i want is something like this (i dont know if it work or there is a better way):
private void fetchSpecificEvent() {
//Fetch event that user already attend
FirebaseRecyclerOptions<ModelEvent> options = new FirebaseRecyclerOptions.Builder<ModelEvent>()
.setQuery(referenceForSpecificEvent, snapshot -> new ModelEvent(
Objects.requireNonNull(snapshot.child("eventID").getValue()).toString(),
...
...
...
)
.build();
...
}
private void getAttendanceCount(){
//Get how many event user already attend
referenceForCount.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
attendanceCount = (int) snapshot.getChildrenCount();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
The main problem is i dont know what reference i use on: referenceForSpecificEvent and referenceForCount
This the JSON:
This the full JSON : https://pastebin.com/k65jhMUC
Sorry for the title, i dont know the keyword for it.
I found the way to do it. Probably not the best (because i cant really explain what i want) but it works.
reference = FirebaseDatabase.getInstance().getReference().child("Attendance");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
for (DataSnapshot eventSnapshot: dataSnapshot.getChildren()) {
//Get Event ID
Log.i(TAG, eventSnapshot.getKey());
for (DataSnapshot userSnapshot: dataSnapshot.child(Objects.requireNonNull(eventSnapshot.getKey())).getChildren()) {
//Get User ID
//Log.i(TAG, userSnapshot.getKey());
if(Objects.equals(userSnapshot.getKey(), stringEmail)){
intCount++;
listEvent.add(eventSnapshot.getKey());
}
}
}
}
else{
Log.i(TAG, "No Value Found");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d(TAG, error.getMessage()); //Don't ignore errors!
}
});

Deleting CardView Data from UI and Firebase Realtime Database?

I have a RecyclerView with CardViews which come from my Firebase Realtime Database for different activities, for example, daily meals. I have added a delete button to the CardView which I would like to implement a delete from UI and database function. I know how to do these both separately, but I am unsure how to update the database after deleting the CardView from the UI.
At the moment, it is deleting from UI but not database, so when I go back to the activity, the card reappears. Each meal has its own random ID, not sure if that makes a difference but thought it is important to note.
Adapter Delete Function:
foodHolder.deleteMeal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
meals.remove(position);
notifyDataSetChanged();
}
});
Meal Activity (Where adapter is set):
mealRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
int total = 0;
for (DataSnapshot mealSnapshot : task.getResult().getChildren()) {
String grams = mealSnapshot.child("grams").getValue(String.class);
if (grams == null) {
textViewFoodCounter.setText("0");
} else {
total += Integer.parseInt(grams);
textViewFoodCounter.setText(String.valueOf(total));
}
if (meals != null) {
noMealsImg.setVisibility(View.GONE);
noMealsText.setVisibility(View.GONE);
} else {
noMealsImg.setVisibility(View.VISIBLE);
noMealsText.setVisibility(View.VISIBLE);
}
progressBar.setMax(1000); // make dynamic
ObjectAnimator.ofInt(progressBar, "progress", Integer.parseInt(grams))
.setDuration(300)
.start();
Meal data = mealSnapshot.getValue(Meal.class);
meals.add(data);
}
foodAdapter = new FoodAdapter(meals);
foodRecyclerView.setAdapter(foodAdapter);
} else {
Log.d("TAG", task.getException().getMessage());
}
}
});
CardView:
Firebase Meal Hierarchy:
You can do something like this. If anything is updated in the firebase database you can load your new data using addValueEventListener and onDataChange.
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance().reference;
DatabaseReference dmoRef = firebaseDatabase.getReference().child(serialId);
dmoRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//get your updated data
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), "Error fetching data", Toast.LENGTH_LONG).show();
}
});

How to check Already existing data in firebase database

I want to check that if classection=Six:B already exist in firebase database then it show toast message please guide I am trying to solve this from 3 days but I cannot solve it Here is my code it doesnot show any error or toast
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users");
Query query = ref.child("Students");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String classsection=""+dataSnapshot.child("classsection").getValue();
if(classsection.equals("Six:B"))
{
Toast.makeText(MaintabclasActivity.this, "Class Six B is Already Exist",
Toast.LENGTH_LONG).show();
}
else
{
// updateclasfiveb();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(MaintabclasActivity.this, "error",
Toast.LENGTH_LONG).show();
}
});
Instead of addListenerForSingleValueEvent ,use onCompleteListener to get data once if you really wants access real time database. because addListenerForSingleValueEvent is for cache data.
// If you have child node id to go through each node use below method.
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users");
ref.child("Students").child("node_id_under_student").get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (!task.isSuccessful()) {
Log.e("firebase", "Error getting data", task.getException());
}
else {
Log.d("firebase", String.valueOf(task.getResult().getValue()));
}
}
});
// Or use query method with ValueEventListener to listen for changes in database.
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/Students");
Query databaseQuery= ref.orderByChild("classsection").equalTo("Six:B");
databaseQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
String classsection=""+dataSnapshot.child("classsection").getValue();
if(classsection.equals("Six:B"))
{
Toast.makeText(MaintabclasActivity.this, "Class Six B is Already Exist",
Toast.LENGTH_LONG).show();
}
else
{
// updateclasfiveb();
}}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
});
A query in Firebase consists of two parts:
A call to order the child nodes of a path on its key, or a certain property.
A call to then filter the child nodes down by a certain value or range.
In your case:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/Students");
Query query = ref.orderByChild("classsection").equalTo("Six:B");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
Toast.makeText(MaintabclasActivity.this, "Class Six B is Already Exist", Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(MaintabclasActivity.this, "error", Toast.LENGTH_LONG).show();
}
});

Shortest Query of Firebase in Android?

I need to check if conversation child is exist.
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference().child("users").child(senderId);
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.hasChild("conversations")) {
if (snapshot.child("conversations").hasChild(receiverId)) {
ConversationLocationModel conversationModel = snapshot.child("conversations").child(receiverId).getValue(ConversationLocationModel.class);
roomId = conversationModel.getLocation();
getAllMessage();
} else {
addinLocation();
}
} else {
addinLocation();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Currently I am using above code to check if child has exist i do not want to check every time so how it can be possible if there is any child exist is there any query for checking child existence.
If you want to check if any child exists, then you can do this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference().child("users").child(senderId).child("conversations");
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()){
//checks if this snapshots exists
}else{
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You can change it depending on your database. But the above will check child("users").child(senderId).child("conversations") if conversations exists then it will enter it and see all its children.

Categories