Firebase addValueEventListener excute later in loop - android

I am using Firebase addValueEventListener to fetch the data from firebase database, below is my code.
DatabaseReference chatMessagesDb = FirebaseDatabase.getInstance().getReference("ChatRooms");
DatabaseReference usersDb = FirebaseDatabase.getInstance().getReference("users");
chatMessagesDb.child(chatRoomId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messages : dataSnapshot.getChildren()) {
Message message = messages.getValue(Message.class); // Message is a data Model for chatMessages.
userDb.child(message.getCreatorId()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I am applying addValueEventListener on chatMessagesDb and providing a key chatRoomId, so it will fetch all the messages from database of the chatRoom with id equals to chatRoomId. Now, for each message I want to fetch the creator of the Message, so I am adding a addValueEventListener on users database to fetch the details of the creator of a Message.
It should work like, for 1st loop of Message it should call the addValueEventListener on users db for the creator of that message, but it doesn't work like this. First, it loop through all the messages, then it starts calling addValueEventListener on users db.
How can I solve it? Please let me know if anyone have idea about this, this would be a great help.
Thanks a lot in advanced.

I think it's little late to answer, but I think other guys who are learning can be helpful. In case of message from db, use ChildValueEventListener. It returns 4 methods to implement, so any change in the db of a particular node will be listened and return that value.

Related

How to compare value with child of Firebase Realtime Database?

I would to compare a value with a child of my Firebase Realtime Database but I don't know how to do. The structure of my database is:
This is the code that I wrote:
email = loadPreferences();
mAuth = FirebaseAuth.getInstance();
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference().child("users");
myRef.orderByChild("email").equalTo(email).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.getValue() != null) {
//loop through the keys
for(DataSnapshot datasnap : snapshot.getChildren()) {
if(!email.equalsIgnoreCase("")) {
myRef.child("users").child("email").child("address").setValue(getAddress());
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
I tried with debugger but when it arrived at "orderByChild()" it skip all and jumps to end. Anyone can help me? Thanks in advance
Data is loaded from Firebase asynchronously, because it needs to be loaded from the cloud. Instead of blocking the app for your users, Firebase instead loads the data in the background and lets your main code continue, which is what you see happening when you step through the code.
Instead of stepping through the code, place a breakpoint on the first line inside onDataChange, and allow the code to run. Then when the data is available, the debugger will hit your breakpoint and you can continue debugging.
You should also implement onCancelled, as you're now ignoring possible problems. At its minimum, this method should be:
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}

Retrieve multiple datab by synchronization from Firebase Android

I am trying send my contacts to firebase one by one and checking if the user is present or not but due to the asynchronous behavior of firebase some information is showing twice.
I want to synchronize this method like this:
loop send one number to firebase, firebase response, save, and continue
for (int i=0 ; i< list.size();i++) {
Check_Contact(list.get(i));
}
public void Check_Contact(String number)
{
DatabaseReference myRef = database.getReference("user").child(number);
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
}
else {
UserProfile row = dataSnapshot.getValue(UserProfile.class);
ls.add(row);
Adapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Can somebody tell me how to synchronize this method?
Firebase Structure
output coming
It is not the firebase async behaviour. You may have duplicate contents in your database. Please check ur database and update a screenshot of your database in your question.
It will be more helpful to understand your question.

FireBase Data Retrieval is getting so much time

I am using Firebase to retrieve data and display it on android. At first it was fine but now it is taking 10 sec on addValueUpdateListner anyone know what is the problem?
final String uid1=FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference
dbref1=FirebaseDatabase.getInstance().getReference("users")
.child(uid1)
.child("signUpAs");
dbref1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
signUpOption=dataSnapshot.getValue(String.class);
Toast.makeText(getBaseContext(),signUpOption,Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
ValueEventListener retrieves all the data at once so if your database grew up in size, it makes sense to take more time than before.

Read Firebase Data Once With ValueEventListener

Within my app I often have the need to read data once. I originally started by using the addListenerForSingleValueEvent() method for this, however I ran into problems using this method as it does not work as I wanted when offline capabilities are enabled (see here the issue: Firebase Offline Capabilities and addListenerForSingleValueEvent)
In the question above it is mentioned that a workaround is to use the addValueEventListener() method, however I do not fully understand how to do this (particularly how to remove the ValueEventListener as soon I am finished grabbing the data I need).
Take this method which I created in a standalone class to query the Users node on Firebase where I store the users FCM Token. It seems to have an issue of not returning the latest token from the server everytime.
public class SendFCMMessage {
String userToken;
String currentUser;
String userName;
ValueEventListener userListener;
public void sendMessage(final String contactNumber) {
final DatabaseReference ref = FirebaseDatabase.getInstance().getReferenceFromUrl(link).child("Users").child(contactNumber);
userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
userToken = user.getToken();
// Send FCM Message after getting user token and then remove event listener
ref.removeEventListener(userListener);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("TAG", "Something terrible went wrong: " + databaseError);
}
};
ref.addValueEventListener(userListener);
}
}
If I remove the line
ref.removeEventListener(userListener);
Then this code works fine, however I would like to know how I could remove the ValueEventListener as soon as I receive the data I need?
Thanks,
R
ValueEventListener vel; //Declared Global
Listen your DatabaseReference like this;
vel = yourDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChanged(DataSnapshot dataSnapShot) {
//Do your stuff here. I suggest you create another method for this if you don't want a problem with inner class.
//For example, workDataSnapshot(DataSnapshot dataSnapShot) <-- Work here
yourDatabaseReference.removeEventListener(vel);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope it helps you.

Firebase Database Datasnapshot

I have a firebase database from which I save and retrieve data from, to and from. I know how datasnapshot works inside an addValueEventListener. The problem is that this is only called or triggered when the firebase database detects change in its data. I only want to access data and read it to be able to store it in an arraylist or the same thing.
I have a code like this:
public void foo(){
DatabaseReference x= FirebaseDatabase.getInstance().getReference().child("x");
reservations.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String userID = client.getId();
for(DataSnapshot snap : dataSnapshot.getChildren()){
if(snap.child("someId").equals(someId)) number++;
if(snap.child("userID").getValue().equals(client.getId())){
isAlreadyReserved = true; // if user has already reserved the item
alreadyReserved();
break;
}
Log.e("isAlreadyReserved: ", isAlreadyReserved+"");
numberOfReservations++;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
if(isAlreadyReserved) {
alreadyReserved();
}
else if(number == numberOfCopies){
// material is no longer available
OtherActivity.showMaterialUnavailable();
}
else{
Reservation reservation = new Reservation();
reservation.setBookId(this.bookId);
reservation.setResID((numberOfReservations+1)+"");
reservation.setUserID(client.getId());
String key = reservations.push().getKey();
reservations.child(key).setValue(reservation);
Log.e("Reservations: ", "reserve successful");
AlertDialog.Builder builder = new AlertDialog.Builder(this.context);
builder.setTitle(R.string.reservationSuccess_title)
.setMessage(R.string.reservationSuccess_body);
AlertDialog dialog = builder.create();
dialog.show();
}
}
You can see that inside onDataChange I only count materials and set some flags, which I can supposedly do outside the ValueEventListener.
But I notice that this is faulty because onDataChange is called only when writing to the Firebase database occurs. Which should not be the case.
What can I do to loop through the values inside the DatabaseReference x without calling onDataChange, or without using DataSnapshot?
You cannot loop inside a DatabaseReference without using a listener. When we are talking about Firebase, we are talking only about listeners. So in order to get those values, you need to use a listener and than get the data out from the dataSnapshot.
What i think your problem is in your case, is that onDataChange method is called in an asynchronously way. This means that everything you are doing outsite this method is actually executed before onDataChange method has been called. So in order to understand what is actually going on, please see this post and this post. Reading this posts, will teach you how to query data in Firebase and how to retrieve data from Firebase asynchronously.
Hope it helps.
In order to get the values of DatabaseReference x, you should use addListenerForSingleValueEvent
x.addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
//do something
}
#Override
public void onCancelled(DatabaseError databaseError)
{
//do something
}
});
as mentioned in the firebase documentation:
public void addListenerForSingleValueEvent (ValueEventListener
listener)
Add a listener for a single change in the
data at this location. This listener will be triggered once with the
value of the data at the location.

Categories

Resources