My application has two database tables: Products and ShoppingCard. So I created a ProductContentProvider and ShoppingCardContentProvider. Each ContentProvider invokes in its onCreate() method a private class that is child of SQLiteOpenHelper.
From my point of view I would make a global static variable DATABASE_VERSION in a separated ConfigBean that is responsible for both content providers. So if I update that all tables are updated.
=> That does not work. Simply the onUpdate event is never fired.
If you specify a DATABASE_VERSION in each content provider, but with different version numbers in each content provider
=> That does not work. Also it makes no sense, from my point of view, because the paramater in SQLiteOpenHelper is called DATABASE_VERSION not TABLE_VERSION. So in other words, you cannot update any table without updating/throwing an event on all onUpgrade listeners.
If you specify a DATABASE_VERSION in each content provider, but with equal version numbers in each content provider.
=> That works.
Question:
Why can't you make the DATABASE_VERSION a public static variable outside to handle upgrades globaly, or am I completely on the wrong path with my architecture?
The solution to my problem was to create a base class to both content providers. This class holds the only instance of SQLiteOpenHelper. This also ensures that all database tables are created.
I found this information in the post of Ali Serghini, November 5th, 2010.
Okay I have found the reason for the strange behaviour:
I think my approach to make the DATABASE_VERSION an external parameter is right, if you have multiple ContentProviders.
I did just forget that there is yet another ContentProvider: A simple ConfigTable to store the settings. I think I hade a mix of different DATABASE_VERSION values in the end, that leads to re-creating the database on every startup.
After referencing a single param from all ContentProviders, everything worked as expected.
Thanks anyway,
Sebastian
Related
I am creating (in android studio) an app which has a couple basic tables. One will be a bunch of exercises (pull ups, push ups ect) and I would like to put a ton of common ones into the table by default.
Where in my code would be the logical place to do that? I have made a databaseHelper class which extends SQLiteOpenHelper. Just not sure if I should..
insert them all in onCreate()
make a databaseHelper method which inserts them all and call it elsewhere
other?
Create a database with your desired data, package it as an asset, and use SQLiteAssetHelper to automatically unpack it into the proper spot for you when you first try to work with the database. This will be faster than running your own transaction(s) to insert the data.
This is a trivial question, but I am afraid to put in production wrong code and that testing in devices/emulator could lead to cache problems that do not mirror the reality.
My assumptions:
As well documented on SO, I need to add a column to my DB, I decided to use ALTER table ADD column
in onUpgrade(), and to change the version in the constructor of the DB from 1 to 2, so that the constructor will recognize that is running the new version and the onUpgrade() function should be triggered.
My 2 problems:
1) MOST IMPORTANT. Let's assume old users will upgrade successfully the db, but what happens with new users that still have to create even the first row of the DB, will they be directed to OnCreate() and not onUpgrade() because version is 2, or to on OnCreate() and then onUpgrade(), or almost impossible directly in OnUpgrade() skipping for some API reason even onCreate()?
In other terms do I need to update the new column changing the old onCreate() comprehending the new added column?
2) in onUpgrade() after
ALTER <table> ADD <column>
logically do I have to CREATE a new table right? Should I call onCreate() that as an updated Table( ex. instead of the original 4 column, now has 5 columns)?
When getWritableDatabase() is called, it checks the database file. If it does not exist, onCreate is called. If it does exist, but has a wrong version, onUpgrade is called.
So onCreate is responsible for creating the database schema of the current version, while onUpgrade is responsible for changing some existing database to have the schema of the current version.
You could share code between onCreate and onUpgrade, but calling that code is your own responsibility; the framework will not check the version again after the onXxx callback has returned.
My question is very simple ! I have seen several applications that define database name(or table name) as a static variable !
why ?
like :
private static final String DATABASE_NAME = "database" ;
can I define it as a final variable ?
Possibly this way you want to say that your DATABASE_NAME is not part of every instance of your class, but a part of the class itself. That would mean that each time you declare an instance of your class, each of those classes won't have a copy of that attribute but they will share that attribute instead.
Quite logic, this is meant to be a static field so why make an instance of it? And yes, it should be a final variable, as it is unlike it will change at execution time.
For convenience. The DB name never changes while the app is running or between instances of the same class - it can only change between app versions. This way if you change the name of your database you won't have to search for it in the entire app - just modify the DATABASE_NAME variable.
I'm using ORMLite in my app.
I had to enable the allowGeneratedIdInsert flag for one of my fields (rows) of a class (table). I did this through annotations.
Now i also need to do this for users which will update the app. This means I need to increment the database version and do the same in my onUpgrade method.
Is there an easy way of doing this? Or do I have to copy my data, drop the table and then recreate it using TableUtils?
Unfortunately ORMLite does not help with this field conversion. You certainly can use the raw-update methods to alter your schema in the onUpdate(...) method:
http://ormlite.com/docs/raw-update
For information about upgrading your schema, see the docs:
http://ormlite.com/docs/upgrade-schema
I need to recognize first launch of my application or activity.
At this time I need to get some information from server create local database and save info to it. What is the best way to do this?
Create any preferences for example FirstLaunch and set true \ false to it.
Check whether my database exists or not.
Something else?
PS. All server calls must be into one transaction. Ormlite supports transactions?
Thanks.
For the "create database at first run"-purpose, you should use an SQLiteOpenHelper, which offers you the onCreate()-method that is called when:
[...] the database is created for the first time.
The Database-file itself will be created for you (you don't have to do this manually). In this method, you can then perform actions like populating your database with standard entry's.
If you want to populate the database with informations you get from your server, there might be a problem when there is no Internet-connection available.
In this case, I would check if there is a connection available:
If there is, get your informations.
If not, show a Toast or some other notification to inform the user.
To determine if your Database has be populated with the standard entry's, you can use the database-version which is also provided by the SQLiteDatabase-class:
When you first create your Database-object, you call
SQLiteOpenHelpers constructor and pass it 0 as the Database
version.
If you successfully populated your database, you use
setVersion()-method to alter it to 1.
Later in the onOpen()-method, which is called when the
database is opened, you can check if the database was populated by
using the getVersion()-method.
If it is populated, call the super-method to open it.
If not, try populating it.
Further more, the getReadableDatabase() / getWritableDatabase()-methods should be called off the main-thread anyways because:
Database upgrade may take a long time, you should not call this method
from the application main thread, including from
ContentProvider.onCreate().
So getting the informations from the Internet can take place in the onCreate() and in the onOpen()-method (if it wasn't successful at the first try). You can (for example) use a Service to do this.
If you want to solve this problem with database:
Create database with MyDatabasaVersion table and store your version in a single row, for example db_version default value is 0. First time when the application starts you check the db_version if 0 you need to start the syncronisation, after it is finishing set the db_version to 1.
The easiest way should be sharedpreferences. you can call it everywhere form the application context and you can put boolean values in it.
Here are all Android storages.
you should try first option Create any preferences for example FirstLaunch and set true \ false to it.