open database:
*使用ContextImpl#openOrCreateDatabase(),返回一个SQLiteDatabase对象。
*可以去继承SQLiteOpenHelper,然后调用getWritableDatabase()可以获取SQLiteDatabase,使用SQLiteOpenHelper去获取,那么就要复写onCreate和onUpgrade方法。
分析SQLiteOpenHelper#getWritableDatabase():
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
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) {//如果版本号为0,则是第一次创建数据库,需要创建数据库文件。就要调用onCreate,所以之后就不用调用onCreate了
onCreate(db);
} else {
if (version > mNewVersion) {//如果version<mNewVersion就需要更新数据库,调用onUpgrade()
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);//设置database版本号为新的版本号
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();
}
}
}
复写SQLiteOpenHelper的onCreate和onUpgrade:
onCreate中一般就是创建数据库表格。可以使用CREATE table IF NOT EXISTS
onUpgrade,看看SettingsProvider的DatabaseHelper#onUpgrade():
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
Log.w(TAG, "Upgrading settings database from version " + oldVersion + " to "
+ currentVersion);
int upgradeVersion = oldVersion;
// Pattern for upgrade blocks:
//
// if (upgradeVersion == [the DATABASE_VERSION you set] - 1) {
// .. your upgrade logic..
// upgradeVersion = [the DATABASE_VERSION you set]
// }
if (upgradeVersion == 20) {
/*
* Version 21 is part of the volume control refresh. There is no
* longer a UI-visible for setting notification vibrate on/off (in
* our design), but the functionality still exists. Force the
* notification vibrate to on.
*/
loadVibrateSetting(db, true);
upgradeVersion = 21;
}
if (upgradeVersion < 22) {
upgradeVersion = 22;
// Upgrade the lock gesture storage location and format
upgradeLockPatternLocation(db);
}
if (upgradeVersion < 23) {
db.execSQL("UPDATE favorites SET iconResource=0 WHERE iconType=0");
upgradeVersion = 23;
}
if (upgradeVersion == 23) {
db.beginTransaction();
try {
db.execSQL("ALTER TABLE favorites ADD spanX INTEGER");
db.execSQL("ALTER TABLE favorites ADD spanY INTEGER");
// Shortcuts, applications, folders
db.execSQL("UPDATE favorites SET spanX=1, spanY=1 WHERE itemType<=0");
// Photo frames, clocks
db.execSQL(
"UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
// Search boxes
db.execSQL("UPDATE favorites SET spanX=4, spanY=1 WHERE itemType=1001");
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
upgradeVersion = 24;
}
//... ...太多了省略一些
if (upgradeVersion < 116) {
if (mUserHandle == UserHandle.USER_OWNER) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
+ " VALUES(?,?);");
loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
if (stmt != null) stmt.close();
}
}
upgradeVersion = 116;
}
if (upgradeVersion < 117) {
db.beginTransaction();
try {
String[] systemToSecure = {
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED
};
moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, systemToSecure, true);
db.setTransactionSuccessful();