I can get data from Firebird DataBase but they are updated only if I restart the activity how to do it without restarting the activity.
The code snippet with the implementation of retrieving data
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long coinsAmount = dataSnapshot.child("coinsAmount").getValue(Long.class);
text.setText(String.valueOf(coinsAmount));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
uidRef.addListenerForSingleValueEvent(valueEventListener);
Change
uidRef.addListenerForSingleValueEvent(valueEventListener);
to:
uidRef.addValueEventListener(valueEventListener);
This way, your listener will be called each time the value in the DB changes,
and not only once.
Read more about difference between valueEvent and singleValueEvent.
Related
I have a very simple code:
// get users poll date, and set in relevant text view
Query query = gameRef.child("users_loto").child("zaalkIb4W0V7MGbekLhqjP34IQi1").orderByChild("pollRank").limitToLast(1);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
nDate = Long.parseLong(ds.child("pollRank").getValue().toString().substring(0, 14));
user_result.setText(String.valueOf(nDate));
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
query.addListenerForSingleValueEvent(valueEventListener);
I ordered it by pollRank - it is the same number as the child name.
It seems to return the last value of the relevant node:
But instead, it always returns the one before :
A very weird behavior...
Any thoughts about why it happens?
Tnx for #ShehanWisumperuma!
gameRef.keepSynced(true) was the correct answer to my issue!!!
Tnx for all of you who tried to help me!
My Firebase Realtime Database has been built by loading an object of the Java class HashMap. In my Android Studio app I'm trying to write a method that takes a String (the key) as input, searches through the database and if the string is found it returns the associated Float (the value), otherwise it returns 0. How can I do this? Any help would be really appreciated!
EDIT: I've tried to follow the suggestions, adapting them to my particular case, but I didn't manage to solve the problem yet.
I wrote the following code in MainActivity:
DatabaseReference myRef;
Float tempValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
myRef = FirebaseDatabase.getInstance().getReference("myRoot");
tempValue=0f;
...
}
public void retrieveValueFromDatabase(String childName, final MainActivity activity){
myRef.child(childName).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Float value=dataSnapshot.getValue(Float.class);
if (value==null){
value=0f;
}
activity.tempValue=value;
//First Toast
//Toast.makeText(activity,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
public void useValues(){
retrieveValueFromDatabase(childName,this);
//Second Toast
//Toast.makeText(this,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
//code using tempValue from here
...
}
If I uncomment the first toast, the correct value inside tempValue is shown, but if I uncomment the second toast, the value of tempValue shown is the default one (0.0). What am I missing?
You need to use addValueEventListener to retrieve data from the database:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("myRoot").orderByChild("name").equalTo("peter");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i("Database", dataSnapshot.child("floatValue").getValue(Long.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
Here, you add a reference to the root node, then query using equalTo() to check if name = peter exists in the database and return the float value.
You should read the guide:
https://firebase.google.com/docs/database/android/read-and-write
I have written this code to fetch the data. But I want to fetch updates without restarting the activity as data changes in real-time in the database.
I want to show data dynamically:
FirebaseDB.batch.child(batch).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//Update recyclerview here
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
If you need to get data in real-time, you should use a real-time listener. To solve this, please change your code to:
FirebaseDB.batch.child(batch).addValueValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//Update recyclerview here
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("TAG", error.getMessage()); //Never ignore potential errors!
}
});
See, I have used Query's addValueEventListener():
Add a listener for changes in the data at this location.
instead of addListenerForSingleValueEvent() which:
Add a listener for a single change in the data at this location.
You are using wrong listener. According to firebase documentation this listener will be triggered only once.
You need to use simple ValueEventListener as stated in docs
Is there any way to pull data from firebase where the code is? I currently have valueEventListeners, but they all run after the code below them, thus invalidating the following code. I want to be able to pull a value exactly where the code is, not later.
As of yet, I have not found anything online about this.
A good example of my problems in the code:
public void onItemClick(AdapterView<?> l, View v, final int position, long id) {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
final String uid = user.getUid();
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
cCESnapshot is null because the intent runs before the valueEventListener.
The onDataChange() is asynchronous, so the only way to use the retrieved data is inside onDataChange(), example:
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
This is an asynchronous operation, when the data will arrive, the onDataChange callback will be triggered. Your startActivty code will be executed sequentially and this is why you get no value in cCESnapshot.
Move the startActivity code inside the listener.
But be careful, because each time the onItemClick click listener will be called, you'll add a value event listener. That way, you'll have multiple calls to onDataChange in each click and so multiple startActivities.
Instead, i recommend using addListenerForSingleValueEvent which will be triggered only after a single change in data.
Im using the Android SDK for firebase database.
In the database I have a structure where I keep the messages ordered by user, that way if I need their messages I just query by user.
myDatabase -> messages -> JonDoe
-> "You forgot your mail"
-> "Buy groceries"
-> JaneDoe
-> "Dog's birthday!"
The problem is if the user doesnt exist the listener keeps waiting forever, and I want to show "You have no messages" in that case. (For example, if I query the user "CharlesDoe" in the example above)
Is there a way to check if a reference exists before/after/during a query?
try this:
DatabaseReference root =FirebaseDatabase.getInstance().getReference();
DatabaseReference user = root.child("myDatabase").child("messages");
user.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.child("CharlesDoe").exists()) {
// run some code
}else{
Toast.makeText(this,"no messages",Toast.Length_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here it will query on node messages and then it will check if the child exists and do the required.
Try this on
DatabaseReference root =FirebaseDatabase.getInstance().getReference();
DatabaseReference user =
root.child("myDatabase").child("messages").child("CharlesDoe");
user.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()) {
// run some code
}else{
Toast.makeText(this,"no messages",Toast.Length_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});