Reputation: 107
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
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
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:
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