ChildEventListener on Android limit to EventType

497 views
Skip to first unread message

David M

unread,
Jan 15, 2015, 2:04:04 PM1/15/15
to fireba...@googlegroups.com
On iOS we can add a listener to observe a specific event type. Specifically, at a top-level node I can listen for children added and not child changed events. Is there a similar method to limit event types on Android. I see that ChildEventListener requires implementing methods for all event types.

Rob DiMarco

unread,
Jan 15, 2015, 7:28:40 PM1/15/15
to fireba...@googlegroups.com
Hi David -

As you mention, the ChildEventListener currently requires implementing methods for all of the child event types. For now, if you only care about one event type, I would simply leave the callbacks for the other event types empty, effectively as no-ops. You won't incur any performance penalty with respect to the Firebase listeners for these event types.

Thanks for the feedback!

Rob
Engineer @ Firebase

On Thu, Jan 15, 2015 at 11:04 AM, David M <dmes...@imagiclab.com> wrote:
On iOS we can add a listener to observe a specific event type. Specifically, at a top-level node I can listen for children added and not child changed events. Is there a similar method to limit event types on Android. I see that ChildEventListener requires implementing methods for all event types.

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/0fc272ef-3012-41d0-b2fb-3e36fcc05571%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

David M

unread,
Jan 16, 2015, 8:58:25 AM1/16/15
to fireba...@googlegroups.com
Hi Rob, thanks for replying. From what I understand, if I setup a very deep tree schema, on iOS, I can add a Child Added listener to the top node and only listen for first level node additions. However on Android, I'm forced to also listen for Child Changed events which may occur at any level of the tree? My coworkers were under the impression that adding only the Child Added listener to the top node would effectively limit the amount of data that is streamed to the device, whereas a Child Changed listener on the same node would cause constant data streaming. Can you clarify the behavior for us?

ai...@imagiclab.com

unread,
Jan 16, 2015, 9:20:15 AM1/16/15
to fireba...@googlegroups.com
Hi, I am the co-worker that implemented the iOS version of the app we are working on. For clarification sake, I will list how I believe the iOS firebase implementation works under the hood, please correct me if I am wrong.

Assume you have a branch with 10,000 nodes that you want to scroll through part of. In iOS I would create a childAdded listener for the top 50 nodes (to limit the data transfer since all 10,000 would be overkill), then as the user scrolled to the bottom of the list, I would either add or expand my existing childAdded listener to encompass more nodes. Simple enough. Also assume you want to have a listener for all 10,000 objects to know if/when they are deleted or changed, which we use to track various states client side (like object counts). Again, in iOS I would create a childChanged/childRemoved listener at the root of the branch encompassing all 10,000 objects, expecting only to have the effected objects return to me as they are effected. 

In iOS it appears to me that a childAdded listener will sync all the child data for the "block" of nodes I am listening for, so we want to minimize that block size. However, childChanged, childRemoved, and childMoved only appears to sync data for the effected objects as they are effected, not the entire branch that it is listening to. The problem as I see it is that Android does not allow for the separation of this behavior, thus there is no way to minimize the data set returned in this example, thus requiring all 10,000 nodes to be returned, or am I completely wrong about how the iOS version is syncing data in the background?

To sum up:
childAdded = sync server to client the entire block of nodes?
childChanged/childRemoved = sync server to client only the effected nodes within the block?

Rob DiMarco

unread,
Jan 16, 2015, 4:50:58 PM1/16/15
to fireba...@googlegroups.com
Hi folks -

I'd be happy to help clarify some of the underlying client behavior. Be sure to follow-up with me if anything said below is unclear.

That conclusion around what data is cached for the different listeners isn't quite right. In actuality, all of the client events (added, changed, removed, and moved) load the same data from the server and cache it on the client.

The best way to see exactly what data is going over the wire is to enable logging in the client. Here's how to do that on the various clients, generally at the beginning of the app:
  • JS:
Firebase.enableLogging(true);
  • iOS:
[Firebase setLoggingEnabled:YES];
  • Android:
Firebase.getDefaultConfig().setLogLevel(Logger.Level.DEBUG);

Adding a single 'child-removed' or 'child-changed' (or any child event) listener to the root of a list in Firebase, without any limits or offsets, will download the entire list to the client. There are important reasons for this behavior, largely boiling down to the fact that Firebase does state synchronization instead of pub-sub, so from the perspective of a Firebase client there is no notion of "only give me events since I came oneline". Let's dig a bit deeper on that subject:

The two biggest reasons for this client behavior worth calling out are (a) offline behavior, and (b) local events, which go hand-in-hand. In the former case, if you had a 'child-removed' event listener established with the server, but went offline, when you came back online we wouldn't know which elements to send down to your client unless we persisted each of those removed elements on the server indefinitely. By sending all elements in your defined window down to the client, when the client comes back online we can invoke your callback / block to tell you precisely which children were removed from the list. Similarly, for local events, if you went offline and your local client removed items from the list or cleared it entirely, we can immediately fire local events with the "correct" state of the data.

It is, admittedly, a little unintuitive that the 'child-removed' event would load the full list on the client. In general, if you're working with large lists in Firebase, the best way to restrict the amount of data being transferred is to always use one form of limiting / windowing or another - generally using two of the three methods in (`startAt()`, `endAt()`, and `limit()`). 

I hope that helps, and let me know if I can assist with anything else.

Have a great weekend -

Rob

David M

unread,
Jan 20, 2015, 10:06:55 AM1/20/15
to fireba...@googlegroups.com
Rob, thanks for clarifying. Can you elaborate on something for us. Consider a scenario where we have a large list of data, and we want to enable a paginated, expanding display (the list keeps growing but the data is fetched in batches). In this case we would create a ChildEventListener with a limitToFirst() modifier, eg, limitToFirst(10). When page 2 is requested, we create a new listener with limitToFirst(20), then remove the previous listener. In this case, would the client sync the first 10 results from the server twice? We're trying to understand what effect this may have on the amount of data that is being synced from the server.

Kato Richardson

unread,
Jan 20, 2015, 10:34:06 AM1/20/15
to fireba...@googlegroups.com
David,

If you attach the second listener before removing the first, the data will still be cached locally and shared between listeners. This applies to listening on child nodes and parent nodes as well.

Cheers,
Kato


ai...@imagiclab.com

unread,
Jan 20, 2015, 5:51:52 PM1/20/15
to fireba...@googlegroups.com
Thank you all for your help so far. One more question if you dont mind. 

Our iOS build is using a pre 2.0 version from the October timeframe, but the Android team just started development and is currently building with the latest 2.x. On the iOS side we make fairly heavy use of the method "- (FQuery *) queryStartingAtPriority:(id)startPriority;" which has been deprecated, and from what we can determine there is no direct analogue. There is a method to sort by key, and a method to sort by priority, and a method to start at a key, but not a method to start at a priority from what I can see. Am I missing something, and/or suggestions? Please and thank you.

Jacob Wenger

unread,
Jan 20, 2015, 5:59:17 PM1/20/15
to fireba...@googlegroups.com
Hey there,

Note that the deprecation of that method means that the method can still be used with those clients, but we will be removing that method in a future release. The concept of priority is what is really being deprecated. Instead of sorting nodes by priority, you should put your priority value in an actual child key and do a sort/start at that child key. This can be as simple as copying your priority value to a /priority/ key (note that this child key could be called anything though, which is one reason why the new methods are more powerful).

Jacob

ai...@imagiclab.com

unread,
Jan 22, 2015, 6:29:24 PM1/22/15
to fireba...@googlegroups.com
Michael,

I am reworking some of our pagination code to make better use of the local cache between listeners. However, I am getting confusing results from the log output that I was hoping you could clarify for me. 

If I have a listener on a location with a limitToLast of 10, and then at some point in the future I create another listener pointing to the same location but with a limitToLast of 20. Based on your earlier post I was expecting to see only the 10 new objects returned in the log under "[Firebase] Got data message:", but I am seeing all 20 instead. 

Is this because the log output happens after the return object has combined the server response with the local cache, or is it actually returning all 20 in the server response (including the 10 duplicates)? Also, if it is combining the local cache with the server response before output, is there any way to display only what is actually being sent from the server? We are trying to be as efficient with data as we can. Thanks.
 


On Tuesday, January 20, 2015 at 10:34:06 AM UTC-5, Michael Wulf wrote:

ai...@imagiclab.com

unread,
Jan 23, 2015, 11:37:01 AM1/23/15
to fireba...@googlegroups.com
Ok, so I spent some time this morning running the scenario listed above through wireshark. Although I can't directly parse the data (encrypted), I can see that each subsequently added listener does bring back more and more data, even if the previous listener to the same location has not yet be released. Which seems to be contradictory to the expected. Thoughts?

Kato Richardson

unread,
Jan 23, 2015, 12:54:41 PM1/23/15
to fireba...@googlegroups.com
Queries are slightly different than normal Firebase refs. Each query will get its own, independent cache and will download data. There's no internal optimization to try and reconcile queries and guess what data might be similar and sharable.

Housekeeping: Since none of these items are related to the original thread, I'd appreciate it if you opened a new discussion for any ongoing help from this point, so that others with similar questions will be able to find the correct thread.

Cheers,
Kato


Reply all
Reply to author
Forward
0 new messages