0

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?

2 Answers2

0

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.

regev avraham
  • 1,102
  • 1
  • 9
  • 24
  • Thanks for answering, but I think the problem still remains. This `addListenerForSingleValueEvent` function is only going to be called when the `DatabaseReference x` performs changes on the Firebase Realtime Database. I need it to go like: `Fetch data from Realtime DB` -> `Process data` -> `Perform necessary changes on Realtime DB` Instead, it goes like: `Perform changes in order to trigger listener` -> `Fetch data from listener` -> `Process data` -> `Perform changes in Realtime DB` – JeobMallari May 06 '17 at 20:53
  • This event happens only one time, and after you set it, it doesn't happen only after data change. Have you tried it? – regev avraham May 06 '17 at 20:56
  • Yes I have tried it. It does not solve the problem. It still needs a data change to perform the process. I need to read the values first before performing data changes. – JeobMallari May 06 '17 at 20:58
  • This is wired, that worked for me. When do you call the foo method? maybe there is a problem around that. – regev avraham May 06 '17 at 21:00
  • I call it inside an alert dialog's onclick listener. the error is not there. im already thinking of using a rest call in an asynctask only to view the contents and take the data that i need, _instead of_ performing a data change to read the data, then doing another data change. – JeobMallari May 06 '17 at 21:08
  • Have you checked that the data ref on wich you set the listener exists? – regev avraham May 06 '17 at 21:22
  • Yes, it exists. I can fetch data cleanly from the Firebase realtime database, but that is not the case. Thanks for answering, I already resorted to using an asynctask for a rest call. Thank you. – JeobMallari May 06 '17 at 21:30
0

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.

Community
  • 1
  • 1
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thanks! Tho I have already solved my problem. I used an `AsyncTask` to make a REST call to the `Firebase` realtime database, and used it to pre-process the data that I need before firing the `onDataChange()` method of its `ValueEventListener`. This way, I can call the `onDataChange()` in just the right time after the data processing. – JeobMallari May 07 '17 at 16:57
  • Nice to hear that. Cheers! – Alex Mamo May 08 '17 at 08:59