This Is My Code
#Override
protected void onStart() {
super.onStart();
control.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
s2=dataSnapshot.getValue(String.class);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
if (s1==s2){
button.setVisibility(View.INVISIBLE);
}
}
}
when trying to control visibility from Firebase above code does not work. If I try same without use of Firebase it works.
Would appreciate any advice
Actually addValueEventListener() is an ASYNC call, so before the value of s2 gets assigned it's being compared in your if(s1==s2) statement & the value of s2 is default or null while comparison.
Instead, you can try hiding your button inside your async call itself as
#Override
protected void onStart() {
super.onStart();
control.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
s2=dataSnapshot.getValue(String.class);
if ( s1.equalsIgnoreCase(s2) )
button.setVisibility(View.INVISIBLE);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
//if (s1==s2) //Remove these lines
//button.setVisibility(View.INVISIBLE);
}
You should call this line:
if (s1==s2) button.setVisibility(View.INVISIBLE);
inside your onDataChange:
#Override
protected void onStart() {
super.onStart();
control.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
GenericTypeIndicator<String> s = new GenericTypeIndicator<String>() {};
s2=dataSnapshot.getValue(s);
if (s1==s2) //you can change this line with "if (s1.equals(s2))"
button.setVisibility(View.INVISIBLE);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
}
because addValueEventListeneris asynchronous, so onDataChange will be called after onStart is finished
Related
I have String values in firebase database
I would like to get this String
in onClick i make a toast for display the value but the value is toasted in the second click
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_souslistecuisine);
cuisinecomplet=(ImageView)findViewById(R.id.cuisinecomplett);
FirebaseDatabase database= FirebaseDatabase.getInstance();
DatabaseReference myRef=database.getReference("Produit");
DatabaseReference key=myRef.child("Cuisine");
DatabaseReference text=key.child("cuisine complet");
text1=text.child("text1");
text1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
txt=dataSnapshot.getValue(String.class);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public void complet(View view) {
Toast.makeText(souslistecuisine.this, txt, Toast.LENGTH_LONG).show();
}
I tried to put text1.addValueEventListener(new ValueEventListener()) in Onclick method but same result
Just add the Toast after you already receive the String value from Firebase, as Firebase callbacks run in background thread and take time to response.
text1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
txt=dataSnapshot.getValue(String.class);
Toast.makeText(souslistecuisine.this, txt, Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Why data in the firebase are created this way and not in the normal way
this is my code
ProductRef.child(IdMesa_1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
facturas.setValue(dataSnapshot.getValue().toString()).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task)
{
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
When you call dataSnapshot.getValue().toString(), you're converting a branch of your JSON tree into a string. When you then write that back to Firebase, it saves it as a string.
If you want to save it in the same structure as before, don't convert the data to a string. So:
ProductRef.child(IdMesa_1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
facturas.setValue(dataSnapshot.getValue());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
The code looks like this:
final DatabaseReference TuidRef = usersRef.child(td);
final DatabaseReference msgRef = TuidRef.child("rec_msg");
final DatabaseReference FuidRef = TuidRef.child("fromUID");
final DatabaseReference secretRef = TuidRef.child("rec_secret");
msgRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot1) {
ms = dataSnapshot1.getValue(String.class);
flag++;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
FuidRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot2) {
fUid = dataSnapshot2.getValue(String.class);
flag++;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
secretRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot3) {
st = dataSnapshot3.getValue(String.class);
flag++;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
String flagS = "" + flag;
Log.i("flag",flagS);
if(flag > 2)
displayMessage();
I used the flag to know how many times the ValueEventListeners are triggered, but the flag is found to be 0, in the log.
td is the uid of the person who receives the message. In the picture below it is same as the parent key of other sibling Childs.
The database looks something like this, when there are no messages:
The database looks like this, when messages are received:
Edit: How can I execute the function displayMessage(), when all three of the listeners have been triggered at once?
The value is added simultaneously to all three of them in the firebase database, though.
You'll never know how many times a ValueEventListeners is triggered in the way do, because the value of flag will always remain 0. This is happening due the asynchronous behaviour of onDataChange() method which is called even before you are trying to get the data from the database. What's really happening is that you are trying to get the data from the database and immediately try to log it while the flag variable has the initial value of 0. Then, when getting the data from the database completes, it changes flag's value, but it's never read again.
A quick solve for this problem would be add three different flags inside each callback and try to log then separately only inside the onDataChange() method like this:
msgRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot1) {
ms = dataSnapshot1.getValue(String.class);
flag1++;
Log.i("flag1", String.valueOf(flag1));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
FuidRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot2) {
fUid = dataSnapshot2.getValue(String.class);
flag2++;
Log.i("flag2", String.valueOf(flag2));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
secretRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot3) {
st = dataSnapshot3.getValue(String.class);
flag3++;
Log.i("flag3", String.valueOf(flag3));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
If you need in your code to get the value of that flag outside the onDataChange() method, 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.
Edit:
msgRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot1) {
ms = dataSnapshot1.getValue(String.class);
flag++;
FuidRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot2) {
fUid = dataSnapshot2.getValue(String.class);
flag++;
secretRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot3) {
st = dataSnapshot3.getValue(String.class);
flag++;
Log.i("flag", String.valueOf(flag));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
I have issues on nested queries I'm trying to do using firebase, seems like the first query (activity1) doesn't wait until the second (activity2) and third query (activity3) finished running, this might return NULL value from the first query. Please look at my sample for more understanding, I've been stuck here for days trying all kind of method but it just wont work. :(
Query query_1= reference.child("Users").child("Room")
.child("Profile");
query_1.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//ACTIVITY 1
Query query_2 = reference.child("Users").child(Room)
.child("Receiver").child("id");
query_2.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//ACTIVITY 2
Query query_3 = reference.child("chatrooms").child("Room")
.child("Creator").child("id");
query_3.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//ACTIVITY 3
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I have a code something like this:
change_status_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mfirebasedatabase.getReference().child("genre_items").child(genre_status_selected).child(genreitem_status_selected).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(genre_status_selected!="" && genreitem_status_selected!="" && dataSnapshot.child("status").getValue().equals("available"))
{
mfirebasedatabase.getReference().child("genre_items").child(genre_status_selected).child(genreitem_status_selected).child("status").setValue("unavailable");
}
else if(genre_status_selected!="" && genreitem_status_selected!="" && dataSnapshot.child("status").getValue().equals("unavailable"))
{
mfirebasedatabase.getReference().child("genre_items").child(genre_status_selected).child(genreitem_status_selected).child("status").setValue("available");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
whenever I click the change status button , it changes the status ,but since it is in the onDataChange it leads to an infinite loop...changing its state infinite no of times...how to get rid of this? how to get out of this loop? I want to change its status once only.
change
addValueEventListener
to this
addListenerForSingleValueEvent
mfirebasedatabase.getReference().child("genre_items").child(genre_status_selected).child(genreitem_status_selected).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(genre_status_selected!="" && genreitem_status_selected!="" && dataSnapshot.child("status").getValue().equals("available"))
{
mfirebasedatabase.getReference().child("genre_items").child(genre_status_selected).child(genreitem_status_selected).child("status").setValue("unavailable");
}
else if(genre_status_selected!="" && genreitem_status_selected!="" && dataSnapshot.child("status").getValue().equals("unavailable"))
{
mfirebasedatabase.getReference().child("genre_items").child(genre_status_selected).child(genreitem_status_selected).child("status").setValue("available");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Use addListenerForSingleValueEvent()
example
database.getReference().child("chats").child(senderRoom).child("messages").addListenerForSingleValueEvent(new ValueEventListener() {
#SuppressLint("NotifyDataSetChanged")
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
database.getReference("chats/"+senderRoom+"/messages").removeValue();
Toast.makeText(ChattingActivity.this, "All chats delete", Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(ChattingActivity.this, "Error! Chats not delete", Toast.LENGTH_LONG).show();
}
});