I’m new to Android development and I’m about to implement simple Preferences for my app. It appears SharedPreferences is a dead end and has lots of warts, so I’m looking at DataStore (non-Proto) vs Room. Since I ALREADY heavily use Room and LiveData (yes, I know Flow is the new hotness) in my app for other things, is there any benefit to using DataStore too? I understand Room is recommended for large or complex data as I’ve already reviewed the following, but I’m hoping a more seasoned developer can further hit this home for me:
https://android-developers.googleblog.com/2020/09/prefer-storing-data-with-jetpack.html
https://proandroiddev.com/lets-explore-jetpack-datastore-in-android-621f3564b57
https://medium.com/better-programming/jetpack-datastore-improved-data-storage-system-adec129b6e48
Thank you.
The official blog post you linked has a section specifically about Room vs DataStore:
If you have a need for partial updates, referential integrity, or support for large/complex datasets, you should consider using Room instead of DataStore. DataStore is ideal for small , simple datasets and does not support partial updates or referential integrity.
User preferences almost always fall into the 'small, simple datasets' that can be easily expressed as key/value pairs (or something more complicated if you want to use the Proto DataStore) that do not need the overhead of a table schema, SQL queries, custom parsing, or the 'relational' part of a relational database.
The problem with datastore is you cannot just fetch or update a part of data from a list like you can with SQLite libraries such as Room. This is true for both Proto and Preferences version. So if you have 10 thousand elements and you save them to DataStore and then you want to update 2 of them based on a condition you'll have to fetch the entire list, manipulate it and put it back. Here Room (or any DB solution) will be a way to go
But if you just want to save user preferences or small data it would be an overkill to use a DataBase - here DataBase Proto will actually be the perfect choice
I am building an Android app, which makes use of Contacts stored in Android Database.
The preferred approach is to use ContentResolver, and then query() as the app's data is exposed by the provider.
Fair enough..!!!
Can, I use Room here for querying the data which are exposed by providers?
Is it a fine approach? As I want to take advantage of abstraction and compile time check and internal mapping?
Not directly.
Room is only for your own internal database.
You could conceivably poll the contacts through its ContentProvider once per day (perhaps through a Job, so this work is done alongside other jobs). This data could then be inserted into your own Room database.
This could have negative reactions from users (why is this App storing my contacts?!). It would also not be updating instantly, only as often as you poll the data manually.
My app tracks school grades, calculates averages, etc. and stores all of this in a SQLite database. If a user has to reinstall or gets a new phone, I'd like to be able to restore their data.
It looks like most developers do this either by backing up to SD card or by using Android Backup Service through Google. I'm not sure which is the better method. I'd like restoring to be simple but reliable. I welcome any comments on this.
One thing I'm trying to understand is why Google says to extend BackupAgent instead of BackupAgentHelper if using a database.
If you have an SQLite database that you want to restore when the user re-installs your application, you need to build a custom BackupAgent that reads the appropriate data during a backup operation, then create your table and insert the data during a restore operation.
Why can't I just back up the database as a file and then restore the file? My SQLiteOpenHelper class already handles upgrades if db versions are different. I guess I could just abort on a downgrade.
Why can't I just back up the database as a file and then restore the
file? My SQLiteOpenHelper class already handles upgrades if db
versions are different. I guess I could just abort on a downgrade.
Reason: same database file may not work on different device models(even though most of the cases, it should work, there are cases where it will fail). It depends on parameters like page size etc set at sqlite engine level. Ideal way is to backup the data rather than copying the whole file
It's suggested that you avoid backing up the whole db file all the time mostly because that's a lot of redundant data traffic, especially if you've only changed one record in a large db. Being able to write per-record updates to the backup system is much more efficient (though of course is not nearly as simple to implement).
The question is : When does GreenDao update the sql database from the session cache?
Let say that I'm querying an existing entity out of the database and than change one of it properties(fields). The changes are performed without directing the sql database in anyway.
So - should I do update on the entity?
When does GreenDao flush it's session cache into the database itself?
What you describe sounds like JPA/Hibernate session cache. greenDAO doesn't have that. It is simpler. There are objects kept in memory and you always update them manually to the database.
Some more information (far from complete):
http://greendao-orm.com/documentation/sessions/
When one generates the GreenDAO code (Entities, DAOs, DaoSession....etc), the DAOs by default extend the AbstractDao class which has a variety of methods for updating the database when needed instead of keeping the update in memory for a while such as (update(T entity), refresh(T entity), updateInTrx(java.lang.Iterable entities)).
For more information check the AbstractDao javaDoc
i have done SQLite database programming for Android, but i dont know anything about
Content-Provider except this: "As i have referred Android Developer page , Android SDK explained about "Content-provider" as it is used to store and retrieve data."
But then,
What is the exact difference between "Content-Provider" and "SQLite Database"?
Which is best to store data, when ?
Any example or helps !!
I found one major difference, as follows:
Storing your data in a database is one good way to persist your data, but there's a caveat in Android-databases created in Android are visible only to the application that created them. That is to say, a SQLite database created on Android by one application is usable only by that application, not by other applications.
So, if you need to share data between applications, you need to use the content provider model as recommended in Android. This article presents the basics of content providers and how you can implement one.
I found this article at this link
Really nice information provided.
What is the exact difference between
"Content-Provider" and "SQLite
Database"?
ContentProvider is a facade -- an API you can implement that exposes databases to other processes. It can be implemented in a way where the data is stored in a SQLite database, but it does not have to be.
Which is best to store data, when ?
That is impossible to answer in the abstract. Generally speaking, unless something is requiring you to use a ContentProvider, just use a database.
I have made many good apps with thousands of users using them which simply used SQLite methods. But that was a while ago and I had to manually write lots of code which now can easily be taken care of by ContentProvider. Back then I was not in favour of using Content Providers because it seemed to only add complexity in the code.
However for last couple of years, as Android has evolved, I have moved to ContentProvider as it saves time and allows you do to more. I now use it extensively. Once you have a Content Provider class written, your life becomes much easier. With ContentProvider I can much easily deal with Cursor Loaders, Loader Callbacks and Bulk Inserts for which I had to write everything manually in the past and still it didn't work as efficiently. Especially when updating the list view, which is now automatically updated thanks to just one notifychange() method. This means now I don't have to type my own listeners and manually updating the content in list views and adapters. Plus, I don't need to worry about opening and closing of databases or worry about memory leaks. That's all handled by the Content Provider. The only problem which once in a while I face is that that you cannot do some complex queries in ContentProviders. In this case you can still use raw queries and use the old fashioned manual interaction with sqlite.
If you have previously written your own DbAdapter, Helper and Observer, you can safely carry them on to your new apps without spending time to convert everything to ContentProvider. But based on my experience, I would highly recommend to move to ContentProvider. It'll take some time to get used to it, but once you have got experience with it, you'll stay with it.
UPDATE 2017
I have now switched to Realm, a much better way to use databases on any platform. Spend a few hours learning it, and save countless hours in your app development career.
1. Content Providers are not Thread Safe
By default content providers are not thread safe. If you have multiple threads using a content provider you can see many different exceptions being thrown and other data inconsistencies. The easiest way to fix this is to use the synchronized keyword on each of the public methods exposed by the content provider.
In this way only one thread at a time can access these methods.
2. Play nice when doing lots of writes
I have the need in the new Serval Maps application to import data from binary files into the database used internally by the application. In order to do this and play nice with the rest of the application it is best to:
Spawn a new thread to undertake the import so other threads are not adversely impacted, in particularly the thread in charge of updating the UI; and
Pause briefly at the end of the each import to give other threads which need to use the synchronized methods more of a chance.
3. Content providers force you to think laterally sometimes
The way that content providers in Android work is to provide a layer of abstraction between the rest of your code and the underlying database. This is mainly due to the fact, as far as I can tell, that content providers can access data from places other than databases.
This means that you can’t execute raw SQL queries on the underlying database and you need to specify the various components of a SQL query using variables passed to the various methods such as the query method. If you have a task that doesn’t fit into the way that SQL is handled by a content provider you have two options:
Think laterally about the query, maybe you can get the data that you need by alternative queries and accessing the results from the cursor; and
Use a URI for accessing the data normally and a special URI that is matched to a specific query for those tasks that don’t have alternatives.
Content Providers are used when you want to share your data across applications.
If you have a database attached with an application and you want another application to use some data, you can implement a content provider that exposes the data
The main difference is: when your app needs to share information to another apps, use Content-Provider. SQLite only storage data for the app who creates it
I read this answer while looking for same doubt, so thought of sharing it.
it states -
It's good practice to provide the extra level of abstraction over your data to make it easier to change internally. What if you decide to change the underlying database structure at a later time? If you use a ContentProvider you can contain all the structural changes within it, where as if you don't use one, you are forced to change all areas of the code that are affected by the structural changes. Besides, it's nice to be able to re-use the same standard API for accessing data rather than littering your code with low-level access to the database.
So, using a content provider would be a good idea.
Think of advanced Content Management Systems. Each object (page, image, news article, event item, etc.) has a content, an address, user permissions, and ways to interact with it from different parts of the system. Content Providers do that for Android. You can now share files or images you may have stored in your application. You can also create custom sharable objects, like bussiness contacts, editable notes, etc. And specify security and the default application to deal with such object when you open them from any other application.
One difference is that Content Providers have platform support for Content Observers. Your going to need to implement your own Observable pattern for a SQLite database.
How to automatically re-query with LoaderManager
ContentObserver for SQLite?