applejuice
applejuice

Reputation: 107

Firebase Child and Value listeners

First of all, I am aware that this question has been asked multiple times, but a recent trouble with my app has piqued my interest in this matter. And I have read the Firebase documentation as well.

What is the difference between ChildEventListener and ValueEventListener Firebase interfaces?

From the topic above, it seems that both Child and Event listeners have the same functions but with different "flexibility", which I think is true.

Just for context, I will provide two examples from my recent project.

Example 1:

Database Structure

{
  "requests" : {
    "pushed_id_1" : {
      "request_name" : "qjvnocnqjd",
      "request_date" : "11 Oct 2017"
    },
    "pushed_id_2" : {
      "request_name" : "qjvnocnqjd",
      "request_date" : "10 Nov 2017"
    }
  }
}

Referring to the structure above, my initial plan was to obtain the value of the last node using the query methods in Firebase. Here is a snippet of the code.

myRef.child("requests").orderByKey().limitToLast(1).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Request request = dataSnapshot.getValue(Request.class);
                Log.d(TAG, "requestDate: " + request.getRequest_date());
            }

The above code gave me a null value for request.getRequest_date(). Then after a few painful searching for a solution, I found the post below.

Retrieve null values from Firebase database Android

a TL;DR of the link above is that the solution is to change the ValueEventListener to a ChildListener instead and it worked wonders in my project. Then, comes my second example.

Example 2:

Database Structure

{
  "users" : {
    "user_uid_1" : {
      "user_name" : "Admin",
      "join_date" : "7 Nov 2017"
    },
    "user_uid_2" : {
      "user_name" : "Member",
      "join_date" : "9 Nov 2017"
    }
  }
}

Here is a snippet of my code to obtain user data.

myRef.child("users").child(userID).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                User user = dataSnapshot.getValue(User.class);
                Log.d(TAG, "userDeets: " + user.getJoin_date());

                }
            }

The code above does not return me a null for user.getJoin_date(). Then, this is when I suddenly want an explanation so that, moving forward, I can better understand how these two listeners work and choose accordingly.

These are my specific questions:

Thank you for reading until this part and I apologize if this question is too long.

Upvotes: 3

Views: 2439

Answers (2)

Peter Haddad
Peter Haddad

Reputation: 80914

These are my specific questions:

If querying is involved, is ChildEventListener the one that I choose instead of the alternative?

From the two examples above, it seems like ValueEventListener is used when I can specify the node that has the Key:Value pair immediately one level below the specified node. On the other hand, ChildEventListener is used when there is no Value involved, just Childs (which is what the "Child" in ChildEventListener is meant for?). Am I right to say this previous statement?

Both valueeventlistener and childeventlistener are kinda the same but they are different from addListenerForSingleValueEvent which reads data only once.

Now, no you can choose any of the two if query is involved, you dont have to use childeventListener always.

For the second question its kinda true what you said, usually in the valueeventlistener we use for loop:

  for(DataSnapshot data : dataSnapshot.getChildren()){

So the data will iterate inside the children of dataSnapshot. But if you use ChildEventListener you dont have to use that for loop above.

But obviously if it is nested more you will have to do that loop in childeventlistener

Upvotes: 1

Frank van Puffelen
Frank van Puffelen

Reputation: 598837

It's much simpler: a ValueEventListener fires with the entire result in one go, a ChildEventListener fires with each child node of the result individually.

To determine if you need a ValueEventListener or a ChildEventListener, there are two things to consider:

  1. Whether your reference points to a single item, or if it's a list.
  2. Whether (in the case of a list) you want to handle each item individually, or if you want to handle them all at once.

If you have a listener that points to a single item, you'll use a ValueEventListener.

If you have a listener or a query that points to a list, no matter if there's only a single child/result, you'll need to take care of that list. You can do that by either using a ChildEventListener or by looping over DataSnapshot.getChildren() in ValueEventListener.onDataChange().

Upvotes: 3

Related Questions