Android中的Sqlite中的onCreate方法和onUpgrade方法的執行時機--

來源:互聯網
上載者:User

標籤:

原文:http://blog.csdn.net/jiangwei0910410003/article/details/46536329

今天在做資料庫升級的時候,遇到一個問題,就是onCreate方法和onUpgrade方法的執行時機的問題,這個當時在操作的時候,沒有弄清楚,很是迷糊,所以寫代碼的時候出現了很多的問題,所以沒辦法就去扒原始碼看了。不過在此之前我講解過一篇關於資料庫升級的文章,但是那裡沒有詳細的講解一下這兩個方法的執行時機,所以這裡就在單獨說一下

關於資料庫升級的文章:http://blog.csdn.net/jiangwei0910410003/article/details/39670813

不多說,下面直接進入主題吧:

首先我們看看SQLiteOpenHelper類的源碼:

它裡面有一個重要的方法:getDatabaseLocked

這裡我們看到當我們的mName變數為null的時候,就會建立一個記憶體資料庫,資料的生命週期是Application層級的,這個mName就是建立資料庫的檔案名稱。

 

當然正常情況下,我們都會傳入一個資料庫檔案名的,所以這個方法一般不會執行的,那麼就走下面的代碼。下面的代碼就是直接開啟一個資料庫。不過我們看到一個特點,就是建立資料庫和Context有關係呢。我們看一下Context中的代碼。不過這裡我們知道Context是一個抽象類別,我們一般會看他的子類ContextImpl實現:

主要看一下getDatabasePath方法和openOrCreateDatabase方法:

首先來看一下openOrCreateDatabase方法:

 

[java] view plaincopy 
  1. @Override  
  2. public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,  
  3.         DatabaseErrorHandler errorHandler) {  
  4.     File f = validateFilePath(name, true);  
  5.     int flags = SQLiteDatabase.CREATE_IF_NECESSARY;  
  6.     if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {  
  7.         flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;  
  8.     }  
  9.     SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);  
  10.     setFilePermissionsFromMode(f.getPath(), mode, 0);  
  11.     return db;  
  12. }  

這裡我們看到其實還是調用了SQLiteDatabase的openDatabase方法

 

 

再來看一下getDatabasePath方法:

 

[java] view plaincopy 
  1. @Override  
  2. public File getDatabasePath(String name) {  
  3.     return validateFilePath(name, false);  
  4. }  

 

 

我們看到這兩個方法都是有一個核心的方法:validateFilePath

 

[java] view plaincopy 
  1. private File validateFilePath(String name, boolean createDirectory) {  
  2.     File dir;  
  3.     File f;  
  4.   
  5.     if (name.charAt(0) == File.separatorChar) {  
  6.         String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));  
  7.         dir = new File(dirPath);  
  8.         name = name.substring(name.lastIndexOf(File.separatorChar));  
  9.         f = new File(dir, name);  
  10.     } else {  
  11.         dir = getDatabasesDir();  
  12.         f = makeFilename(dir, name);  
  13.     }  
  14.   
  15.     if (createDirectory && !dir.isDirectory() && dir.mkdir()) {  
  16.         FileUtils.setPermissions(dir.getPath(),  
  17.             FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,  
  18.             -1, -1);  
  19.     }  
  20.   
  21.     return f;  
  22. }  

這個方法其實很簡單,就是通過傳遞過來的資料庫名稱name,然後構建一個資料庫檔案File對象返回即可。

 

 

那麼上面的幾個方法我們可以總結功能:

通過傳遞過來的資料庫名稱name,建立一個File對象,然後得到資料庫檔案的path..傳遞給SQLDatabase的openDatabase方法中,開啟資料庫檔案

 

下面我們繼續來看那個流程:

 

[java] view plaincopy 
  1. final int version = db.getVersion();  
  2. if (version != mNewVersion) {  
  3.     if (db.isReadOnly()) {  
  4.         throw new SQLiteException("Can‘t upgrade read-only database from version " +  
  5.                 db.getVersion() + " to " + mNewVersion + ": " + mName);  
  6.     }  
  7.   
  8.     db.beginTransaction();  
  9.     try {  
  10.         if (version == 0) {  
  11.             onCreate(db);  
  12.         } else {  
  13.             if (version > mNewVersion) {  
  14.                 onDowngrade(db, version, mNewVersion);  
  15.             } else {  
  16.                 onUpgrade(db, version, mNewVersion);  
  17.             }  
  18.         }  
  19.         db.setVersion(mNewVersion);  
  20.         db.setTransactionSuccessful();  
  21.     } finally {  
  22.         db.endTransaction();  
  23.     }  
  24. }  

當開啟資料庫檔案的時候,我們就開始進行操作了,今天講的內容最主要的就是上面的判斷了:

 

首先擷取資料庫的目前的版本,當版本號碼為0的時候,就會執行onCreate方法(當資料庫檔案第一次建立的時候版本號碼就是0)如果版本號碼不為0,同時和最新版本號碼進行比較,如果大於的話,就執行升級操作onUpgrade方法,否則就執行降級onDowngrade方法,不過降級方法實現很簡單:

直接拋出異常,也就是說資料庫不允許降級操作的,這個也符合正常情況。

 

好了。通過上面的分析,下面我們就對這兩個方法做一下總結:

public abstract void onCreate(SQLiteDatabase db);
public abstract void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion);


SQLiteOpenHelper會自動檢測資料庫檔案是否存在。如果存在,會開啟這個資料庫,在這種情況下就不會調用onCreate()方法。如果資料庫檔案不存在,SQLiteOpenHelper首先會建立一個資料庫檔案,然後開啟這個資料庫,最後調用onCreate()方法。因此,onCreate()方法一般用來在新建立的資料庫中建立表、視圖等資料庫組建。

也就是說onCreate()方法在資料庫檔案第一次建立時調用。


先看看SQLiteOpenHelper類的構造方法再解釋onUpdate()方法何時會被調用。
public SQLiteOpenHelper(Context context,String name,CursorFactory factory,int version);
其中name參數表示資料庫檔案名(不包括檔案路徑),SQLiteOpenHelper會根據這個檔案名稱建立資料庫檔案。version表示資料庫的版本號碼。如果當前傳入的資料庫版本號碼比上次建立或升級的版本號碼高,SQLiteOpenHelper就會調用onUpdate()方法。也就是說,當資料庫第一次建立時會有一個初始的版本號碼。當需要對資料庫中的表、視圖等組建升級時可以增大版本號碼,再重新建立它們。現在總結一下onCreate()和onUpgrade()調用過程。


1.如果資料庫檔案不存在,SQLiteOpenHelper在自動建立資料庫後會調用onCreate()方法,在該方法中一般需要建立表、視圖等組件。在建立前資料庫一般是空的,因此不需要先刪除資料庫中相關的組件。
2.如果資料庫檔案存在,並且目前的版本號高於上次建立或升級的版本號碼,SQLiteOpenHelper會調用onUpgrade()方法,調用該方法後會更新資料庫的版本號碼。在onUpgrade()方法中除了建立表、視圖等組件外,還需要先刪除這些相關的組件,因此,在調用onUpgrade()方法前,資料庫是存在的,裡面還原許多資料庫組建。

綜合上述兩點,可以得出一個結論:

如果資料庫檔案不存在,只有onCreate()被調用(該方法在建立資料庫時被調用一次)。如果資料庫檔案存在,會調用onUpgrade()方法升級資料庫,並更新版本號碼。

Android中的Sqlite中的onCreate方法和onUpgrade方法的執行時機--(轉)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.