Firebase onChildEventListener slow - android

I'm using an onChildEventListener to retrive 10'000 children.
The time it takes to complete the operation is around 5 seconds.
During that time, the app freezes.
Is there a way to make it faster?
Also, I tried to use a ValueEventListener and found that cycling through children is way faster. Anyway, that wasn't a reliable solution, so I switched back to onChildEventListener.

The data retrieval process is exactly the same whether you use a ValueEventListener or a ChildEventListener. The only difference is in how the events are raised/callbacks are fired in your app. In addition: all network activity to the database happens on a separate thread.
This means it is not the retrieval of the data that freezes your app, but more likely the way you handle the data in your onDataChange() callback. If you're doing substantial work there, you'll want to do so off the main thread.

Related

Android (Kotlin): Risks of running Room query on main thread ( < 1400 data values )

I'm wondering what the possible drawbacks are to running my queries on the main thread. At the moment I am loading data from a database using Room and am using this data to generate graphs for the user.
I have already tried putting my queries into separate threads using a runnable, but I am having issues with the application attempting to use data which has not yet been loaded due to the separate thread not finishing it's operation in time. I understand that I could implement some sort of listener or notification, but even then, the user will have to wait an undetermined amount of time before they may view the content because the data for the graphs that they are wanting to view never loads before the button that loads them is clicked.
I have done quite a bit of research and found that it is unadvisable to put the queries on the main thread because it could possibly hang up the thread for a long time and give a poor user experience. So, assuming that I will never exceed 1400 data members, should I worry about this? Are there any caveats that I have not been informed of?
Edit: I am testing the device on a Samsung SM-J106B which is running Android 6.0.1 and I have not noticed any impact on performance even when loading the max of 1400 data members.
DB queries could take long enough that they would cause the UI to skip frames causing a bad visual experience or worse trigger an app not responding exception.

Firebase: for notifications use childEventLisetener or SingleEvent?

I have an android app that uses Firebase for the backend. In my database, I have a section called USER_NOTIFICATIONS which gets populated with some information when user's post gets liked.
Now, in the app, should I have a ChildEventListener that gets triggered any time a notification happens or should I have a SingleValueEventListener inside a function and call it every 20 seconds inside a Runnable? Is it expensive to run SingleEventListener in a Runnable?
The majority of the resource usage of a listener comes from the data it reads. When you attach a listener to a location, it reads the data from that location and fires the relevant events.
If you use addListenerForSingleValueEvent that's all it does. But if you use addValueEventListener or addChildEventListener, the listener stays active and will also be called if the data is updated afterwards.
a listener on a piece of data that never changes is quite cheap. But keeping a listener on data that changes frequently is as expensive as the size of the data changes.
In other words: there is no way to tell what to do without knowing all of the above. Without knowing those, I'd go for the simplest possible approach, put some measurements in place, and optimize as you discover more about your app's behavior.
I'm assuming you want to your app to respond to changes in the database, in which case you should use ChildEventListener. You can specify different behavior for 4 actions (onChildAdded, onChildChanged, onChildMoved and onChildRemoved).

Invoking Firebase listener to run

I'm trying to determine whether or not I download data in my android application. I can do this by making the method return true when it does download data, but the listener doesn't seem to be invoked until all other code is finished running (meaning it waits until a pause in your code). So I'm wondering if there is a way to sort of "forcibly" invoke these listeners? Perhaps by creating the listener in a different thread? Would this work or would it be a waste of time? I've already tried to sleep on the main thread for a few seconds, but that doesn't seem to do it either. If it wouldn't work, could you explain when exactly these listeners are invoked? Thanks in advance.
To add onto my question, I am NOT using the realtime database. I understand how realtime triggers work, but I am using the Firestore, so I am only getting data once, not getting realtime updates :)
As you have already noticed with the API calls that deal with reading and writing data are fully asynchronous. This means that the call always returns immediately, without blocking the code to wait for a result. The results come some time later, whenever they’re ready, since it may take some time for this. Depending on your connection speed and the state, it may take from a few hundred milliseconds to a few seconds before that data is available. So Firebase, already is using another thread (other than the main thread) to get the work done.
Calling a synchronous function on your app’s main thread could freeze the app indefinitely, which is a terrible UX. On Android, it could also soft-crash with an Application Not Responding (ANR) dialog.
Doug Stevenson, has explained in his post everything that you need to know about Fireabse asynchronous behaviour and what you need to do/avoid when dealing with Firebase.

Firebase single value listener calls server even when local cache is available and has not changed

My Firebase database has setPersistenceEnabled=true. When offline all the listeners work fine and fetch data from the local cache.
But, when online, Firebase is making a network call each time I use a addListenerForSingleValueEvent on the same node, even though I have a local cache and nothing has changed on the server.
I have two items at the node I'm attaching the listener to, and I see the following reported after setting log level to debug. This network activity is repeated every time I use the listener while online, even within sub second delays. My understanding is that if Firebase has local data, then server calls won't be made. Any sync checks might happen in the background and with efficient network usage.
conn_18 - received data message: {r=20, b={s=ok, d={}}}
conn_18 - received data message: {r=21, b={s=ok, d=}}
I am trying to aggressively reduce network usage on my app, and any suggestion to stop/reduce Firebase network activity would be very helpful.
Been digging into this myself.
As far as I can tell, the second call you are experiencing is simply the network saying "Hey, there's no updates", and you're not charged for any reads.
As far as reducing the network activity, I think this is just how it works, and how you want it to work (its the actual listening part of the listener). If you don't want that, use a getDocument call, rather than a listener.
This is based on a few things:
When you look at snapshot.metadata.isFromCache (iOS SDK) for a query, the call will come twice. first from cache and then from the server. However, if you print a statement under snapshot.documentChanges, ONLY the cached call will print.
I did an experiment re-loading a view in iOS ~20 times. I also made on small change to my data. I then waited 5-10 minutes and looked at the usage on: https://console.cloud.google.com/firestore/usage. My total read count went up by 3, which means I was only charged for the update. Reloading the view a bunch of times was NOT charged.

Is there a standard pattern for updating android views?

I'm currently building an android application with quite a few different connected activities. In each activity I've got a private updateView() method to update all the textViews and stuff on that screen. This gets called in the onResume() method so that each time the activity comes to the front it's views will be updated.
Is this the right way to do things or is there a more standard pattern for keeping your views in sync with the data?
I think that you are doing this correctly. onResume would be the perfect time to update your views, I assume you are only updating if there is actually new data to be displayed?
If retrieving the data during the updateView method takes a long time then you should do it in an AsyncTask to avoid clogging the UI Thread which will make your app hang.
In fact any data retrieval like getting data from the web or reading from your apps database should be done in an AsyncTask. This is because even if your data retrieval seems to take milliseconds on your device it may conceivably take longer on another, less powerful device.

Categories

Resources