设置this.getReadableDatabase()之后,为什么需要关闭数据库?

时间:2019-06-02 14:00:22

标签: java android sqlite

我在下面的链接中遇到与用户相同的问题。他提到,仅在特定的android设备上创建一个空数据库(对我来说,这是像素,对他来说,是另一台android手机)。但是,在大多数android手机上,当前代码中的行为均有效。

有一个解决方案发布,有人提到要在db.close()之后添加this.getReadableDatabase()来解决此问题。但是,我不确定为什么要修复它,以及为什么该行为仅在某些Android设备上有效?

以下是链接: http://www.anddev.org/networking-database-problems-f29/missing-table-in-sqlite-with-specific-version-of-desire-hd-t50364.html

2 个答案:

答案 0 :(得分:1)

简而言之,如果您使用的是历史上经常使用的方法,则无需使用正确的技术,但如下所示,则必须这样做:-

使用this.getReadableDatabase()的原因是在data / data / the_package /目录中创建数据库文件夹/目录。如果数据库目录不存在,则资产的典型副本将失败,并出现ENOENT错误。

在默认情况下使用SQLite使用日志模式日志记录的情况下,这没有问题,因此从历史上讲,使用this.getReadableDatabase()解决方法一直有效。

但是,在Android Pie(28)中,SDK已更改为默认情况下使用预写日志记录(WAL),这是一种更新的高级日志记录方法。此方法使用两个文件,这些文件具有改进的安全措施。一种是文件被标记/标记为属于创建它们的数据库。

因此,当使用旧方法复制数据库而不关闭数据库时,两个文件(后缀为-wal和-shm的数据库文件)存在,并且很可能包含日志记录数据(例如创建任何表)。但是,它们不会被标记为用于复制数据库,因此(我相信)是重新创建数据库的(因为由于数据库与-shm和-wal文件之间的不匹配而无法打开复制的数据库),因此随之而来的是找不到表错误。

使用WAL关闭数据库/连接会导致提交数据,因此为什么在this.getReadableDatabase()工作后立即关闭数据库。

但是,正确的解决方法是使用File方法检查并创建数据库目录(如果不存在)。这样就无需打开数据库,这很浪费资源,也不需要关闭数据库,这也浪费了资源(即,实际上已执行已记录的操作,并且将数据写入磁盘以及-wal和-shm文件也会被读取和重写)。

答案 1 :(得分:0)

我认为这个问题是由于每个Android版本都带来了不同的SQLite版本,并且一些供应商也自定义了SQLite库版本。正如您从this link中所读到的:

Android API SQLite Version
API 27  3.19
API 26  3.18
API 24  3.9
API 21  3.8
API 11  3.7
API 8   3.6
API 3   3.5
API 1   3.4

希望有帮助。