I am trying to update my mcustDelivery status, from "Accept" to "Enroute" in Firebase after user press enroute button.
but whenever, I press enroute button, the firebase change to "Enroute" and immediately changes back to "Accept".
This is my setOnClickListener for enroute button.
OrderStatus.Java
enroute.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDatabase.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
dataSnapshot.getRef().child("mcustDeliveryStatus").setValue("Enroute");
enroute.setImageResource(R.drawable.greenenroute);
deliver.setImageResource(R.drawable.bluedeliver);
enroute.setMaxWidth(266);
enroute.setMaxHeight(150);
deliver.setMaxWidth(266);
deliver.setMaxHeight(150);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
this below code is where i get the the Accepted status on ViewNewOrder.java
accept.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDatabase.child(getKey()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
dataSnapshot.getRef().child("mcustDeliveryStatus").setValue("Accepted");
Intent orderStatus = new Intent(ViewOrderRequest.this, orderStatus.class);
startActivity(orderStatus);
Toast.makeText(getApplicationContext(),"notification sent to customers",Toast.LENGTH_LONG).show();
//start new activity show root map
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(),"not updates",Toast.LENGTH_LONG).show();
}
});
}
});
It's simple you have used addValueEventListener for accepting the request you are changing the value in the same reference. So the addValueEventListener triggered up and again change the value to accept. For writing, data refer firebase docs for read and write
private DatabaseReference mDatabase;
mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child(getKey()).child("mcustDeliveryStatus").setValue("Accepted")
or simple fix change that addValueEventListener to addListenerForSingleValueEvent
Related
I am going to make a simple app and I am completely new to Android development. I want to develop an edit button to save my data in the Realtime Database. This is my code:
holder.edite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final DialogPlus dialogPlus=DialogPlus.newDialog(holder.title.getContext())
.setContentHolder(new ViewHolder(R.layout.dialogcontent))
.setExpanded(true,2100)
.create();
View myView=dialogPlus.getHolderView();
EditText title=myView.findViewById(R.id.hTitle);
EditText description=myView.findViewById(R.id.hDescription);
Button submit=myView.findViewById(R.id.usubmit);
title.setText(myItems.getName());
description.setText(myItems.getAddHomeworkDescription());
dialogPlus.show();
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Map<String,Object> map=new HashMap<>();
map.put("name",title.getText().toString());
map.put("addHomeworkDescription",description.getText().toString());
DatabaseReference myRef = getInstance().getReference().child("Homework");
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
// String key = myRef.push().getKey();
myRef.child(uid).child()
.updateChildren(map);
dialogPlus.dismiss();
}
});
}
});
This is how my firebase database looks like
What I want to add into .child() to get highlighted(In the image) Unique id direction. But this unique ID is not always same. It change everythime when user create new one.
You will either have to know the push key (-NN...) value of the node you want to update already, determine it with a query, or loop over all child nodes and update them all.
Update a specific child with a known push key
myRef.child(uid).child("-NNsQO7O9lh0ShefShV")
.updateChildren(map);
Update children matching a specific query
Say that you know you want to update the node with name "test12", you can use a query for that:
myRef.child(uid).orderByChild("name").equalToValue("test12").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot nodeSnapshot: dataSnapshot.getChildren()) {
nodeSnapshot.getRef().updateChildren(map);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
Update all children
This is a simpler version of the above, by removing the query condition:
myRef.child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot nodeSnapshot: dataSnapshot.getChildren()) {
nodeSnapshot.getRef().updateChildren(map);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
I'm trying to execute some code in my addValueEventListener based on conditions of values in database, but when data changes, listener execute conditions based on old data, and at the second try listener perform data which I want to use. however data change listener perform listenr(-1) data. To be more clear, if "disable" or "stop" child exist I don't want to execute the code, but after data are updated and these children not existing, conditions when I call AddMessage method not executing again, but it execute method when I call for the second time, it perform correctly till next update of the data where it start again same issue.
sendMessage.setOnClickListener(new View.OnClickListener() {#Override
public void onClick(View v) {
AddMessage();
}
});
private void AddMessage() {
nListener = RootRef.child("List Ref").child(messageReceiverID).child(messageSenderID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
if (!dataSnapshot.hasChild("disable") && !dataSnapshot.hasChild("stop")) {
HashMap <String,String> chatMessageMap = new HashMap <>();
chatMessageMap.put("from", messageSenderID);
chatMessageMap.put("type", "check");
chatMessageMap.put("content", messageText);
MessagesRef.child(messageReceiverID).push().setValue(chatMessageMap);
RootRef.child("List Ref").child(messageReceiverID).child(messageSenderID).removeEventListener(nListener);
} else {
RootRef.child("List Ref").child(messageReceiverID).child(messageSenderID).removeEventListener(nListener);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
sendMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String stoppedUser;
myDbref = FirebaseDatabase.getInstance().getReference().child("List Ref").child(<UID_OF_RECEIVER_OF_MESSAGE>);
myDbref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
try {
stoppedUser = dataSnapshot.child(<UID_OF_SENDER>).child("stop").getValue().toString();
//Now use if-else statement
if(<UID_OF_RECEIVER> == stoppedUser){
Toast.makeText(getApplicationContext(), "You are blocked.", Toast.LENGTH_LONG).show();
} else {
AddMessage();
}
}catch (Throwable e){
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Though you can get <UID_OF_SENDER> by using FirebaseUser currentUserUID = FirebaseAuth.getInstance().getCurrentUser();
Make sure you put the value of <UID_OF_RECEIVER> correctly and also correct the database path if needed.
I have two tables - cartOrders and placedOrders. cartOrders is used to add products to cart, and placedOrders is activated when the user presses "Place Order" button.
I need to copy data from cartOrders to placedOrders when the user clicks the "Place Order" button, but I'm not able to do so.
cartDatabase = FirebaseDatabase.getInstance().getReference("cartOrders");
cartQuery = cartDatabase.child(orderID).orderByChild("productQuantity").startAt(1);
placedOrdersDatabase = FirebaseDatabase.getInstance().getReference("placedOrders");
placedOrderQuery = placedOrdersDatabase.child("orderID");
placeOrderButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
cartDatabase.child(orderID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//Logic to add data to data to placedOrders.
String name = dataSnapshot.child("productName").getValue(String.class);
System.out.println("ProductName: " + name);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent(getApplicationContext(), OrderPlacedActivity.class);
intent.putExtra("ORDER_ID", orderID);
startActivity(intent);
}
});
In the code, I was checking if the code is picking up the data from the database, but it wasn't. The output is null. Both the tables have the same structure.
Any help will be appreciated.
Thanks!
My cartOrders table structure:
cartOrders:
----------OrderID:
-----------------ProductID:
---------------------------ProductID:
---------------------------ProductName:
---------------------------ProductPrice:
---------------------------ProductQty:
#Alex Mamo answered this question on a different question.
private void copyRecord(Query fromPath, final DatabaseReference toPath) {
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
toPath.setValue(dataSnapshot.getValue()).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isComplete()) {
System.out.println("Complete");
} else {
System.out.println("Failed");
}
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
fromPath.addListenerForSingleValueEvent(valueEventListener);
}
The code works fine.
Link:Moving or copying data from one node to another in firebase database
I have a code for change messageText from database entry:
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.edit:
AdapterView.AdapterContextMenuInfo tm = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int position = tm.position;
final DatabaseReference ref = adapter.getRef(position);
ref.child("messageUserId").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (FirebaseAuth.getInstance().getCurrentUser().getUid().equals(dataSnapshot.getValue().toString())) {
ref.child("messageText").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
input.setText(dataSnapshot.getValue().toString());
sendMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ref.child("messageText").setValue(input.getText().toString());
input.getText().clear();
Toast.makeText(Chat.this, "Изменено", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
break;
}
return false;
}
Code ref.child("messageText").setValue(input.getText().toString()) works excellent, but after it code starts up again from
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
input.setText(dataSnapshot.getValue().toString());
And everything goes in a circle - the data from messageText is inserted into the EditText input and I can again change the text.
How to stop executing code after first changing messageText?
ValueEventListener's onDataChange() method:
This method will be called with a snapshot of the data at this location. It will also be called each time that data changes.
With other words, even if it is a write, an update or even a delete operation, this method is triggered. This is also happening in your case, you're using the same reference ref.child("messageText") to add data and also to listen for changes and that's why you have this behaviour. This is happening over and over again. To solve this, you need to change the logic of your code, by creating two different events. onClick to write the data to the database and attach the listener so it cannot be related to that event.
Right code:
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.edit:
AdapterView.AdapterContextMenuInfo tm = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int position = tm.position;
editText = adapter.getRef(position);
editText.child("messageUserId").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (FirebaseAuth.getInstance().getCurrentUser().getUid().equals(dataSnapshot.getValue())) {
editText.child("messageText").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
input.setText(dataSnapshot.getValue().toString());
editMessage();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
} else {
Toast.makeText(Chat.this, "Запрещено", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
return true;
}
private void editMessage() {
sendMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editText.child("messageText").setValue(input.getText().toString());
Toast.makeText(Chat.this, "Изменено", Toast.LENGTH_SHORT).show();
input.getText().clear();
sendMessage();
}
});
}
private void sendMessage() {
sendMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (input.getText().toString().trim().equals("")) {
Toast.makeText(Chat.this, getString(R.string.edittext_null), Toast.LENGTH_SHORT).show();
} else {
FirebaseDatabase.getInstance()
.getReference()
.push()
.setValue(new ChatMessage(input.getText().toString(),
Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getDisplayName(),
FirebaseAuth.getInstance().getCurrentUser().getUid(),
payload,
avatar,
uploadedAttach
));
input.setText("");
}
}
});
}
It was necessary to simply return to the button its original action and use addListenerForSingleValueEvent instead addValueEventListener.
a2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//below
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
ra2 = dataSnapshot.child("a2").getValue(String.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//fetching face value
ref.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
rface = dataSnapshot.child("face").getValue(String.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//fetching nothingdb which is equals to "zero" in Firebase by default.
ref.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
nothing = dataSnapshot.child("nothingdb").getValue(String.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//fetching addeddb which is equals to "one" in Firebase by default.
ref.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
added = dataSnapshot.child("addeddb").getValue(String.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//starting if condition
if (ra2==nothing){
if (rface==nothing){
a2.setBackgroundResource(R.drawable.rounded);{
Firebase refChild = ref2.child("a2");
refChild.setValue("rounda2");
refChild = ref2.child("face");
refChild.setValue("one");
}
else if (rface==added) {
a2.setBackgroundResource(R.drawable.crossed);
{
Firebase refChild = ref2.child("a2");
refChild.setValue("crossa2");
refChild = ref2.child("face");
refChild.setValue("zero");
}
}
}
});
}
});
I am trying to use the above written code so that once I click on the button the background image of the button is changed based on the data present in the Firebase but the If Condition is not working for reason.
It just ignores if (ra2==nothing){ and also the next if conditions.
The listener onDataChange() callbacks are asynchronous. ra2, nothing, added, and rface will not contain valid results when you compare them for equality because the onDataChange() methods will not yet have executed. This answer to a related question explains the execution order in more detail.
In addition, to compare Strings for equality you cannot use the == operator. You must use the equals() method or TextUtils.equals().
#qbix's answer is true, your if condition actually work but it does not receive the value of ra2, rface, nothing, and added yet.
Also, why should you create 4 different ValueEventListener while you listening to the same reference? You can use just 1 listener then put your if condition inside onDataChange, like this:
a2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ra2 = dataSnapshot.child("a2").getValue(String.class);
rface = dataSnapshot.child("face").getValue(String.class);
nothing = dataSnapshot.child("nothingdb").getValue(String.class);
added = dataSnapshot.child("addeddb").getValue(String.class);
//starting if condition
if (ra2.equals(nothing)) {
if (rface.equals(nothing)) {
a2.setBackgroundResource(R.drawable.rounded);
Firebase refChild = ref2.child("a2");
refChild.setValue("rounda2");
refChild = ref2.child("face");
refChild.setValue("one");
} else if (rface.equals(added)) {
a2.setBackgroundResource(R.drawable.crossed);
Firebase refChild = ref2.child("a2");
refChild.setValue("crossa2");
refChild = ref2.child("face");
refChild.setValue("zero");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled", databaseError.toException());
}
});
}
});