We are using firebase realtime database and I was thinking about implementing a cache locally to reduce repeated calls.
So I came up with an algorithm which involves room persistence library.
stream only the latest data from firebase
store in room cache
when requested fetch all data from room cache and return
But then I started thinking about the cache that firebase provides and started realizing that I might be able to avoid room library at all.
stream only the latest data from firebase
when requested call fetch data using a singleValueListener
Since we are using single value listener only the cached data would be fetched from firebase.
What are the drawbacks of using the second approach? I know that firebase cache is limited to 10MB so that might be one
The one big thing you need to know here is that the cache managed by the SDK is almost fully outside your control. You can set the size of the cache, and you could clear it by trying to find the database file it uses, but otherwise, you can't configure it.
If you write code on your own, will have to make every decision about how it works, and it will be a lot of code to get everything right.
Unlike in Cloud Firestore, where offline persistence is enabled by default, in Firebase realtime database to enable offline capabilities you need to use the following line of code:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
This means that you'll have by default a local copy of your database. So there is no need to add another one. So in this way you'll only get new data, otherwise everyhing is you get is from cache.
Related
It is about Firebase's local cached data in Android.
If the Android user, has 1-2 years data in Firebase,
is there a way to enable, setup, or filter Firebase persistence in local,
so that it only create local cache for the last month ?
So we don't the whole data in local cache, but only the last month.
The Firebase local cache is not designed to be manually populated. It's managed automatically, and you don't have much control over what gets stored in it. It will store data from recent queries, and it will evict data that hasn't been used. You can't choose which data will or will not be cached - it work with everything or nothing at all.
The local cache is meant to be helpful when the user temporarily loses their network connection. It's not meant for full offline support.
If you need a cache for very specific data that you can control, you will need to build that yourself.
The android app I am currently developing will mainly run offline. However while online, the users can connect to the DB to download the data they need. Furthermore they are able to manage the data offline, so they can remove the data they don't want to use. The users cannot modify the online database.
I am using Firebase with its Persistence enabled feature, to save the date for online use. My problem is, that I just cannot manage the data properly.
Since firebase downloads the whole database:
Is there a way to choose, which queries I want to download form firebase?
If not, can I delete those queries I don't want to use, from local content?
It looks like you don't want the sync feature of the firebase database.
However while online, the users can connect to the DB to download the
data they need. Furthermore they are able to manage the data offline,
so they can remove the data they don't want to use. The users cannot
modify the online database.
set write as false for this table in the rules and the modification will not be possible, since you have enabled disk persistence firebase will read the newer updates but wont write the user changes. Also it might discard the existing changes of the user(which the user removed) during the sync and put the newer ones from the cloud, so you might(as I have never tried this) end up doing the sync yourself, please search and read up on this.
Since firebase downloads the whole database: Is there a way to choose,
which queries I want to download form firebase? If not, can I delete
those queries I don't want to use, from local content?
You will have to turn off on the sync on the each of your table like shown below
DatabaseReference dbRef=FirebaseDatabase.getInstance().getReference("table-name");
dbRef.keepSynced(false);
Refer here in the docs. I think this has to be done on each node as there is no way to turn it off on the entire firebase realtime DB except disable disk persistance which you want in your case.
IMHO it looks like you are using firebase as a place to store your data in the cloud, in case the sync feature ends up discarding your local changes to sync the online ones you should consider using SQL-lite DB with Room ORM as it will serve your purpose of just fetching the data and modifying it locally, however the tradeoff here is that you will have to maintain the data in a proper manner to query the newer changes or see if there is any updates/deletes on any of the older records.
I wanted to store the specific path in Firebase database (JSON) in local phone storage, not all data at the realtime-Firebase database. Say I have a news-feed path for each user in my Firebase-database and I want to save only the news-feed which is specified for the user instead of loading whole useless data on the local storage of user's mobile.
I read this paragraph from the official Firabase site which mentioned that
The Firebase Real-time Database synchronizes and stores a local copy of the data for active listeners. In addition, you can keep specific locations in sync.
DatabaseReference scoresRef = FirebaseDatabase.getInstance().getReference("scores");
scoresRef.keepSynced(true);
If this is the solution to my question, then I can use this line directly without writing that line
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Those two bits of code are not really related. They don't do the same thing.
keepSynced(true) effectively keeps a listener active on the given reference, from the moment it's called, for as long as the app is running, so that the local version of the data is always in sync with the remote version on the server.
setPersistenceEnabled(true) just activates local caching of the data read by the SDK. When persistence is enabled, the app can still query data previously read. It takes effect for all data read by the SDK. While persistence is enabled, you can't control which data is cached - all read data is cached up to 10MB max. When the max is reached the oldest data will be evicted from the cache.
According to me the best way will be to parse the Firebase JSON data and map it into an object and then save only data that you need in a local storage (News-feed in your case), and then access it later whenever you need it.
For this, you can use Paper DB as a local storage to store specific data and use it whenever you need to. It stores data as a key value pair so you can access your data with the same key you inserted it with in the database. (Just like shared preferences work).
It stores data as cache in your local storage and uses Kryo serialization framework which is pretty fast for I/O operations.
Or you can also use Room (a google library) with SQLite to achieve this task.
Haven't tried Room but i think it will suite your purpose.
Here's the official documentation for Room
I am developing a chat app that uses firebase database to store data. The usual approach while developing a chat app is to keep the database nodes synced so that you access the messages offline. So the problem rises when I implement the firebase offline capabilities to keep the data nodes synced. Firebase suggests two required steps for accessing data offline:
Enabling disk persistance
this is enabled according to the documentation by using this line of code (in my case I add it in application class):
FirebaseDatabase.getInstance().setPersistanceEnabled(true);
and
Keeping a node synced
this is enabled by simply adding keepsynced(true) to any databasereference that you wish to keep synced, like this:
ChatNode.keepSynced(true);
What is the difference between the two?
According to the firebase team answers on this site, I deduced that:
1) (Disk persistance) stores the data on the device disk to use them when needed, and data is stored wether you write data or read data.
a) If you write data offline: data is stored on disk and is sent to database when you go online again.
b) If you read data offline: the listener that was read online and was kept in disk and stored, you will be able to read it offline from disk.
2) (keep synced true) will keep a database reference synced in 2 ways:
a) If you are also using (disk persistence) with (keep synced) you will be able to keep data synced on disk ... which seems to be the default behavior of (disk persistence).
b) If you are using (keep synced) alone then you only store to what is known as the app memory.
The problem
I did set both of the methods, but my app is now very laggy and slow and sometimes stops on its own.
The question
If all the things that I said above are true, then would this method of offline capability be a heavy load on my app?
If I kept many listeners synced and set persistence enabled, then would the disk become full of data? Should I clean the data? Is the data on disk cleaned by itself in both methods? Is data cleaned by itself from memory?
I want to avoid the lagging and slow response in my app, thanks for your help.
You are right about your assumptions. If you are using FirebaseDatabase.getInstance().setPersistenceEnabled(true); means that Firebase will create a local copy of your database which also means that every change that is made while you are offline, will be added to a queue. So, as this queue grows, local operations and application startup will slow down. So the speed depends on the dimension of that queue. But rememeber, Firebase is designed as an online database that can work for short to intermediate periods of being disconnected and not as an offline database.
Second, if are using many listeners, don't forget to remove the listener accordingly to the life-cycle of your activity like this:
databaseReference.removeEventListener(valueEventListener);
I'm facing a pretty big problem today: I decided to use Parse as a backend for my mobile application. When retrieving data from server, Parse put the result in a local cache so we can use it offline too, which is great. But when adding or updating an object offline, Parse has no mechanism to update the local cache, which leads to big problems when the app has to be used offline.
I decided to maintain a local cache by myself using SQLite : I look on the server entries and on the local cache entries and then, using the dates, I manage to synchronize the data. The problem is that the updatedAt and createdAt fields are set when data are saved in the backend (which is normal), but then how do I know that an entry created offline is older or younger that the online data ? I could use the phone's time but that's quite random knowing that there could be a difference of some minutes.
Any idea?
I'm even open about new tools to use. I mean I'm not focused on Parse so if you have the perfect tool just tell me!
you could set a last synced time in shared preferences and if the updated or created time is > the last sync time then you know it is new then update the last sync time again when your sync is done
How about saveEventually()? Based on the explanation in the API docs, I think this will solve the problem.
Also, one more suggestion, if you want to cache your ParseObject, instead of the painful SQLite and tables and all, you could use internal storage to save the object as is explained in this article.
There is a problem on Class with pointer.
Known bug: https://groups.google.com/forum/#!topic/parse-developers/arRBB7S559M