Android中的Sqlite中的onCreate方法和onUpgrade方法的执行时机

时间:2022-09-23 18:44:13

1、今天在做数据库升级的时候,遇到一个问题,就是onCreate方法和onUpgrade方法的执行时机的问题,这个当时在操作的时候,没有弄清楚,很是迷糊,后来看了相关的博客由于转发受限所以copy了一下,接下来就一起分享一下。

首先我们看看SQLiteOpenHelper类的源码:

它里面有一个重要的方法:getDatabaseLocked

Android中的Sqlite中的onCreate方法和onUpgrade方法的执行时机

这里我们看到当我们的mName变量为null的时候,就会创建一个内存数据库,数据的生命周期是Application级别的,这个mName就是创建数据库的文件名。

当然正常情况下,我们都会传入一个数据库文件名的,所以这个方法一般不会执行的,那么就走下面的代码。下面的代码就是直接打开一个数据库。不过我们看到一个特点,就是创建数据库和Context有关系呢。我们看一下Context中的代码。不过这里我们知道Context是一个抽象类,我们一般会看他的子类ContextImpl实现:

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

首先来看一下openOrCreateDatabase方法:

  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方法:

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

我们看到这两个方法都是有一个核心的方法:validateFilePath

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

这个方法其实很简单,就是通过传递过来的数据库名称name,然后构建一个数据库文件File对象返回即可。

那么上面的几个方法我们可以总结功能:

通过传递过来的数据库名称name,创建一个File对象,然后得到数据库文件的path..传递给SQLDatabase的openDatabase方法中,打开数据库文件

下面我们继续来看那个流程:

  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. db.beginTransaction();
  8. try {
  9. if (version == 0) {
  10. onCreate(db);
  11. } else {
  12. if (version > mNewVersion) {
  13. onDowngrade(db, version, mNewVersion);
  14. } else {
  15. onUpgrade(db, version, mNewVersion);
  16. }
  17. }
  18. db.setVersion(mNewVersion);
  19. db.setTransactionSuccessful();
  20. } finally {
  21. db.endTransaction();
  22. }
  23. }

当打开数据库文件的时候,我们就开始进行操作了,今天讲的内容最主要的就是上面的判断了:

首先获取数据库的当前版本,当版本号为0的时候,就会执行onCreate方法(当数据库文件第一次创建的时候版本号就是0)如果版本号不为0,同时和最新版本号进行比较,如果大于的话,就执行升级操作onUpgrade方法,否则就执行降级onDowngrade方法,不过降级方法实现很简单:

Android中的Sqlite中的onCreate方法和onUpgrade方法的执行时机

直接抛出异常,也就是说数据库不允许降级操作的,这个也符合正常情况。

好了。通过上面的分析,下面我们就对这两个方法做一下总结:

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方法的执行时机的更多相关文章

  1. Android中的Sqlite中的onCreate方法和onUpgrade方法的执行时机--(转)

    原文:http://blog.csdn.net/jiangwei0910410003/article/details/46536329 今天在做数据库升级的时候,遇到一个问题,就是onCreate方法 ...

  2. EF Core 中DbContext不会跟踪聚合方法和Join方法返回的结果,及FromSql方法使用讲解

    EF Core中: 如果调用Queryable.Count等聚合方法,不会导致DbContext跟踪(track)任何实体. 此外调用Queryable.Join方法返回的匿名类型也不会被DbCont ...

  3. Java中的class类的cast方法和asSubclass方法

    一般来说cast是转型的意思,但是学java的时间也不短了,class类居然还有cast这个方法,这里来学习一下这个cast有何用. 第一次看到这个cast是在Spring的源码中, spring-f ...

  4. 在 CSS 中表示颜色的hex code方法和rgb方法

    hexadecimal code(十六进制编码),简写为 hex code. 我们通常使用 decimals,也就是十进制数字,它对每一位数字使用符号0到9来表示.Hexadecimals (或 he ...

  5. HashSet中的元素必须重写equals方法和hashCode方法

    http://jingyan.baidu.com/article/d5a880eb8fb61d13f147cc99.html 1.为什么必须重写这两个方法. 2.什么事hashSet去重,符合什么样的 ...

  6. ASP.NET Core 中文文档 第二章 指南(4.10)检查自动生成的Detail方法和Delete方法

    原文 Examining the Details and Delete methods 作者 Rick Anderson 翻译 谢炀(Kiler) 校对 许登洋(Seay).姚阿勇(Mr.Yao) 打 ...

  7. Hibernate中evict方法和clear方法说明

    Hibernate中evict方法和clear方法说明 先创建一个对象,然后调用session.save方法,然后调用evict方法把该对象清除出缓存,最后提交事务.结果报错: Exception i ...

  8. ThinkPHP 中M方法和D方法详解----转载

    转载的地址,http://blog.163.com/litianyichuanqi@126/blog/static/115979441201223043452383/ 自己学到这里的时候,不能清除的分 ...

  9. Mapper类/Reducer类中的setup方法和cleanup方法以及run方法的介绍

    在hadoop的源码中,基类Mapper类和Reducer类中都是只包含四个方法:setup方法,cleanup方法,run方法,map方法.如下所示: 其方法的调用方式是在run方法中,如下所示: ...

随机推荐

  1. 深入学习jQuery选择器系列第五篇——过滤选择器之内容选择器

    × 目录 [1]contains [2]empty [3]parent[4]has[5]not[6]header[7]lang[8]root 前面的话 本文介绍过滤选择器中的内容选择器.内容选择器的过 ...

  2. Windows Platform Predefined Macros

    https://msdn.microsoft.com/en-us/library/b0084kay.aspx

  3. iOS开发之检查更新

    iOS设备检查更新版本: #pragma mark - 检查更新 - (void)checkUpdateWithAPPID:(NSString *)APPID { //获取当前应用版本号 NSDict ...

  4. chisel中pviews命令无法使用

    chisel是用Python写的LLDB调试器插件,用来调试iOS应用非常方便,相关下载安装链接如下:https://github.com/facebook/chisel.本人安装之后,在xcode里 ...

  5. php文件的管理

    一.先做一下简单的查看文件功能,文件中的文件和文件夹都显示,但是双击文件夹可以显示下一级子目录,双击"返回上一级"就可以返回到上一级目录 (1)先将需要管理的文件遍历出来,可以加个 ...

  6. (转)ElasticSearch学习

    (二期)21.全文搜索引擎Elasticsearch [课程21]elasticsearch.xmind82.1KB [课程21]lucene.xmind0.8MB [课程21]基本用法....api ...

  7. python的导包问题

    有事会遇到在python代码中导入包错误问题,本文简单对python包的引入做简单介绍 简单说,我认为python导包一共有3种情况,分别是: 要导的包与当前文件在同一层要导的包在当前文件的底层(就是 ...

  8. 三维数组—— 与宝玉QQ群交流 之三

    鞠老师 12:50:34 A[excel文件名][excel.sheet][sheet.行][sheet.列] 构成四维数组 计131-张振渊 12:51:54 a[1][0][0][3]? 鞠老师 ...

  9. JavaScript:Function/Object/prototype/__proto__

    console.log(Object.__proto__===Function.prototype); //true console.log(Object.prototype.__proto__); ...

  10. C\C++各路高手以及操作系统专家请进来杀死这个进程

    通常情况下编写一个程序,能够点击关闭button正常结束程序,也能够使用任务管理器结束任务,还能够使用taskkill等命令杀死进程,实在都不行也能够直接重新启动计算机. 可是,这些方法真的都管用吗? ...