Get realtime data change update when data changes on Firebase Realtime Database - java

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

Related

How to make two Firebase database calls one inside the other Java Android

I want to make two database calls one inside the other and make use of the first call data. Since firebase database calls are asynchronous this is not behaving the way I want.
I HAVE two database nodes Users, Chats.
I want first query through one Users at a time and take the user id and then query through the Chats model and check if the id in Users and Chats nodes are same
Something like this.
database.getReference().child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
list.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
users = dataSnapshot.getValue(Users.class);
users.setUserId(dataSnapshot.getKey());
database.getReference().child("Chats").child(auth.getUid() + users.getUserId()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
//ADD USER TO LIST UPDATE UI
list.add(users);
}
else{
//DON'T ADD USER
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Hope I made the problem clear.

Firebase Realtime Databse DataSnapshot only Read the last value in the child

I'm calling addValueEventListener inside the button click, but this method only reads the last item in the node. I want to read all the child value in the node What went wrong here?
btnorder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshot1:dataSnapshot.getChildren())
{
SelectedItems si=dataSnapshot1.getValue(SelectedItems.class);
si.getItemname();
Toast.makeText(MyBookedItems.this, ""+si.getItemname(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
I think you can create an array list and put all snapshot data into it, and then you can find the last data of the list with the value you find by subtracting one from the length of the list. Sorry for my bad English :( I have tried to explain in the solution in the code below)
ArrayList<SelectedItems> selectedItems = new ArrayList<SelectedItems>();
for(DataSnapshot dataSnapshot1:dataSnapshot.getChildren())
{
SelectedItems si=dataSnapshot1.getValue(SelectedItems.class);
selectedItems.add(si);
}
selectedItems.get(selectedItems.size());
It's read all the values but I got the output as a Toast message, because of that I only see the last value)

How to update data from Firebase Database without restarting Activity

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.

How do I pull data from firebase into android studio at the exact point in the code?

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.

Updating a List Size for all users

I am trying to make it so that when a user creates an open game, in my Firebase Database the name of the game is the size of the list. So the very first game created the name of it will = 0, and if another user creates a game then the game will be labeled 1 and so on.
I have it set up right now so that the games are labeled the size of the game list, but the list isn't really updating. The games keep getting called '0' because it thinks the list is empty even though I have visual confirmation in the app that there are items being added to the list.
So my question is: How can I make it so the list continuously updates each time a game is added, and how can I make it so that it updates for all users and not just the user who created the game?
This is what I have setup right now. Here are the variables I am using for the list and the integer getting the list size
ArrayList<String> openGames = new ArrayList<>();
int gameSlot = openGames.size();
Here is what I use to name the game when it is created.
gameMaker = new GameMaker(hp.uid, userName, wagerD, gameSlot);
FirebaseDatabase.getInstance().getReference("FCGames").child(Integer.toString(gameSlot))
.setValue(gameMaker).addOnCompleteListener...
And this is what I have to add the game to the list.
cgRef.child(Integer.toString(gameSlot)).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
openGames.add(userName);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
So again my question is how can I make this list update correctly and how can I make it update for all users on the app?
Edit
Here is what I did with my onChangeData
cgRef.child(Integer.toString(gameSlot)).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
wager = (String) dataSnapshot.child("wager").getValue();
gameSlot = openGames.size();
adapter.notifyDataSetChanged();
}
and now the openGames.add is in my createGameLobby method.
FirebaseDatabase.getInstance().getReference("FCGames").child(Integer.toString(gameSlot))
.setValue(gameMaker).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
openGames.add(userName);
Toast.makeText(FlipCoinLobby.this, "Game creation successful.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(FlipCoinLobby.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
^^ that is just the important snippit from the method. And then I have an onClickListener that creates that calls that method when a button is pressed
In below code segment, you did that openGames.add(username) in onDataChange listener. I think it is an incorrect use of this ondatachange function
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
openGames.add(userName);
adapter.notifyDataSetChanged();
}
please use this to get data from db and update your data. Then push your data to db. You didn't use snapshot value also. You can get most recently updated data from dataSnapshot . Use it to update user data then push it to db

Categories

Resources