I tried to create an SQLite database and do some stuff with it. But I found that my onCreate method is not even invoked!!
I am sending a message to LogC
Let me clear the on the logic flow. Here is Lazy-initialization concept.
The (super) constructor on DatabaseHandler will not invoke onCreate method. Calling DatabaseHandler constructor will initializes: context, database name, factory that creates the database, database version, and database error handler.
getWritableDatabase() > getDatabaseLocked() > - SQLiteDatabase.create()
OR
getReadableDatabase() > getDatabaseLocked() > - SQLiteDatabase.create()
Answer: After your database gets created successfully, your configurations changes, next time again getReadableDatabase() or getWritableDatabase() calls getDatabaseLocked() and there onCreate(db) method inside getDatabaseLocked() gets executed.
Explanation:
The above SQLiteDatabase.create() method is responsible to create SQLiteDatabase in the disk.
But the process in lazy-initialization (mean, it doesn't make everything ready. It creates those objects on the runtime if you need them. For this it used a lot of if..else statements).
If you see the full body of getDatabaseLocked(), this is below. [You can search onCreate() method inside the body of getDatabaseLocked()]
private SQLiteDatabase getDatabaseLocked(boolean writable) {
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
// Darn! The user closed the database by calling mDatabase.close().
mDatabase = null;
} else if (!writable || !mDatabase.isReadOnly()) {
// The database is already open for business.
return mDatabase;
}
}
if (mIsInitializing) {
throw new IllegalStateException("getDatabase called recursively");
}
SQLiteDatabase db = mDatabase;
try {
mIsInitializing = true;
if (db != null) {
if (writable && db.isReadOnly()) {
db.reopenReadWrite();
}
} else if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
try {
if (DEBUG_STRICT_READONLY && !writable) {
final String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
} else {
db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
mFactory, mErrorHandler);
}
} catch (SQLiteException ex) {
if (writable) {
throw ex;
}
Log.e(TAG, "Couldn't open " + mName
+ " for writing (will try read-only):", ex);
final String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
}
}
onConfigure(db);
final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
if (db.isReadOnly()) {
Log.w(TAG, "Opened " + mName + " in read-only mode");
}
mDatabase = db;
return db;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
}
}
}
Please note, inside the body of getDatabaseLocked() method, there are so many if.. else cases. These if.. else cases determines your current environment (configuration), and based on your current environment they call appropriate methods to initialize/configure whatever needed.
Also, note: All the callbacks methods in your DatabaseHandler (class that implemented SQLiteOpenHelper) are called inside the getDatabaseLocked() body.
Source code SQLiteOpenHelper.java:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteOpenHelper.java
Source code SQLiteDatabase.java:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/database/sqlite/SQLiteDatabase.java
Sample to follow: https://github.com/uddhavgautam/SQLiteBasicSample