是否曾經呼叫onUpgrade
方法SQLiteOpenHelper
?如果是這樣,它什麼時候被調用,什麼時候調用?如果開發者沒有調用它,爲什麼它在那裏?這個功能真的發生了什麼?我已經看到了所有表格的例子,但是之後有評論說,放棄所有表格並不是你應該做的。有什麼建議麼?有沒有叫onUpgrade方法?
回答
當您使用比已打開的數據庫版本更新的版本構造SQLiteOpenHelper時,會調用它。要做什麼取決於舊版本和新版本之間的數據庫更改。唯一的情況是,當您不刪除更改的表格時,更改記錄的內容超過了添加的列。然後,您可以使用ALTER TABLE語句將新列添加到表簽名。
如果您正在使用SQLiteOpenHelper,則每次更改數據庫版本時都會調用onUpgrade。 對此有一個額外的要求。數據庫名稱必須保持不變。
Old Version:
dbName = "mydb.db"
dbVersion = 1
New Version:
dbName = "mydb.db"
dbVersion = 2
在onCreate的內容提供者中,您創建了一個採用這些參數的SQLiteOpenHelper實例。你SQLiteOpenHelper實施應該是這樣的:
public static final class MySQLiteOpenHelper extends SQLiteOpenHelper {
public MySQLiteOpenHelper(Context context, int dbVersion, String dbName) {
super(context, dbName, null, dbVersion);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Code to create your db here
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Code to upgrade your db here
}
}
對於那些你想知道的確切時刻誰當onUpgrade()
被調用,它是要麼getReadableDatabase()
或getWriteableDatabase()
在通話過程中。
對於那些不清楚它如何確保它被觸發的人,答案是:當提供給SqLiteOpenHelper
的構造函數的數據庫版本更新時,會觸發它。這裏現在是一個例子
public class dbSchemaHelper extends SQLiteOpenHelper {
private String sql;
private final String D_TAG = "FundExpense";
//update this to get onUpgrade() method of sqliteopenhelper class called
static final int DB_VERSION = 2;
static final String DB_NAME = "fundExpenseManager";
public dbSchemaHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
// TODO Auto-generated constructor stub
}
到... onUpgrade()
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
sql = "ALTER TABLE " + fundExpenseSchema.Expense.TABLE_NAME + " ADD COLUMN " + fundExpenseSchema.Expense.FUNDID + " INTEGER";
arg0.execSQL(sql);
}
實際上,只有調用getWriteableDatabase()時纔會調用onUpgrade。 – 2014-01-13 15:59:25
謝謝你的解釋 – 2014-03-05 05:20:42
@DoctororDrive - 也調用'getReadableDatabase()';都調用'getDatabaseLocked(布爾可寫)' – CJBS 2014-09-12 21:32:09
審查所有的職位和運行調試代碼仍不清楚我的時候我會看到onUpgrade獲取調用。我開始認爲Android有一個嚴重的缺陷..
本頁面上的信息導致我的最終決議。感謝所有貢獻者!
這解決了這個問題對我來說...
public class DatabaseHelper extends SQLiteOpenHelper {
public static String TAG = DatabaseHelper.class.getName();
private static final int DATABASE_VERSION = 42;
private static final String DATABASE_NAME = "app_database";
private static final String OLD_TABLE = "old_and_useless";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(newVersion > oldVersion) {
Log.d(TAG, "cool! you noticed.");
db.execSQL("DROP TABLE IF EXISTS " + OLD_TABLE);
// other calls like onCreate if necessary
} else {
Log.d(TAG, "Hey! didn't you see me?");
}
}
public void checkDatabaseVersion() {
SQLiteDatabase db = this.getWritableDatabase();
// if the DATABASE_VERSION is newer
// onUpgrade is called before this is reached
}
// other code removed for readability...
}
這是真的,getWritableDatabase()和getReadableDatabase()不會導致onUpgrade通話。我沒有檢查其他方法,因爲這些方法符合我的需求。
堅持讀書,起腳來了...
這段代碼在我最初的活動使我明白,當我終於明白了DB版本我調試期間更新...... 啊!
DatabaseHelper dbHelper = new DatabaseHelper(this);
dbHelper.checkDatabaseVersion();
注:調用DatabaseHelper構造更新數據庫版本
構造函數調用後,該數據庫被標記爲新的版本。在調用getWritableDatabase()或getReadableDatabase()之前殺死應用程序,然後使用新版本。此後,新的執行從不調用onUpgrade方法,直到DATABASE_VERSION再次增加。 (感嘆!現在看起來很可笑 :)
我的建議是在應用程序的早期階段添加某種「checkDatabaseVersion()」。或者,如果你創建一個SQLiteOpenHelper對象,請確保你的應用程序死亡之前調用其中一種方法(getWritableDatabase(),getReadableDatabase()等))。
我希望這可以節省別人同樣的頭撓! ..:p
展望SqliteOpenHelper
源代碼,我們可以知道onCreate()
,onUpgrade()
和onDowngrade
被調用的getWritableDatabase()
或getReadableDatabase()
方法。
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
return getDatabaseLocked(false);
}
}
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;
}
}
. . . . . .
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();
}
}
}
據實際上是調用當你調用getReadableDatabase
或。
深入瞭解:
你傳入存儲在一個名爲mNewVersion
變量SQLiteOpenHelper
構造函數的版本號。而已。此時什麼都沒有發生。
每次調用getReadableDatabase或getWritableDatabase時,它都會調用一個名爲getDatabaseLocked
的方法。此方法將獲取數據庫的現有版本號並將其與mNewVersion
進行比較。
- 如果給定名稱的數據庫不存在,它會調用
onCreate
- 如果新版本比舊版本,它會調用
onUpgrade
更大。 - 如果新版本低於現有版本,則會引發異常。
- 如果它們相等,它將繼續並打開數據庫。
我應該在onCreate和onUpgrade中寫什麼?
onCreate
應該包含第一次創建模式的代碼。
您可以將第一次空onUpgrade
,因爲它不會被第一次調用。當你想在後期改變表格結構時,該代碼應該放在這裏。
SQLiteOpenHelper。java(源代碼)
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
return getDatabaseLocked(false);
}
}
private SQLiteDatabase getDatabaseLocked(boolean writable) {
.
.
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);
}
- 1. 有沒有測試方法處理併發呼叫的方法?
- 2. didUpdateLocation方法從來沒有叫
- 3. Rails的NoMethodError的方法,我沒有叫
- 4. 的onCreate()SQLiteOpenHelper的方法不叫既不onUpgrade也不使用getReadableDatabase()
- 5. didRegisterForRemoteNotificationsWithDeviceToken方法有時不叫
- 6. 力mapstruct不叫有*方法
- 7. 呼叫只有父方法
- 8. applicationWillTerminate沒有叫
- 9. 沒有呼叫
- 10. Backbone.js的listenTo問題,對象的翻譯:有沒有方法「叫」
- 11. Express.js:對象#<IncomingMessage>有沒有方法「叫」
- 12. onUpgrade()方法無法正常工作
- 13. onServiceConnected並沒有叫
- 14. 沒有呼叫clientaccesspolicy.xml
- 15. onActivityResult並沒有叫
- 16. onUpgrade和onCreate不運行時,我叫它
- 17. 有沒有辦法在改造呼叫中獲得服務方法名稱?
- 18. Ext.form.Panel有沒有方法「getEl」
- 19. 有沒有方法getBackgroundPage
- 20. 有沒有Ruby dealloc方法?
- 21. Sequel有沒有last_insert_id方法?
- 22. 有沒有sendToActivity()方法?
- 23. 有沒有方法文字?
- 24. 有沒有protractor.promise.when()方法?
- 25. 號碼:命令按鈕並沒有叫管理bean方法
- 26. 導航控制器委託方法沒有收到呼叫
- 27. UIView不會出現和drawRect方法從來沒有叫
- 28. 沒有「log.xxxx」的Scala呼叫記錄方法
- 29. 擴展SurfaceView的onDraw()方法從來沒有叫
- 30. 代表方法沒有收到呼叫,從層到場類
該更改還可能是添加新表,在這種情況下,您可能不會刪除任何現有表。 – CommonsWare 2010-07-02 07:49:38
但是如何提前知道你會修改表格?或者您每次發佈更新時都必須更改方法。 – 2010-07-02 13:26:11
您知道何時更改數據庫並在onUpgrade中添加另一個案例。因此,當用戶更新應用程序時,SQLiteOpenHelper知道現有數據庫已過時並採取相應的操作。查看一段Android源代碼以供參考:http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=packages/SettingsProvider/src/com/android/providers /settings/DatabaseHelper.java – ognian 2010-07-02 13:42:53