3

我目前正在研究 SQLiteDatabase 和相关类,目的是更好地理解它如何处理并发(我当前的解决方案有效,但我觉得我实际上可能在做多余的工作,因为它是在假设并发的情况下完成的不为我处理)。

对,关于 SQLiteOpenHelper 的 android 文档说明了以下关于 getWriteableDatabase 方法的内容

一旦打开成功,数据库就会被缓存,所以每次需要写入数据库时​​都可以调用这个方法。(确保在不再需要数据库时调用 close()。)

我有点不清楚正在缓存什么(所以我目前有一个为我做缓存的包装器)。那么,这里发生了什么?两个 SQLiteDatabase 实例是围绕缓存/静态实例包装的吗?

另外,实际的锁定是如何处理的?如果我有两个单独的 SQLiteDatabase 实例,由同一个 SQLiteOpenHelper 实例创建,那么这些是事务安全的吗?就像我在一个事务上以独占模式开始一个事务,然后在另一个线程中启动另一个事务,在另一个 SQLiteDatabase 实例上,我希望第二个事务在第一个事务完成之前不会启动。这是它的工作原理吗?

4

2 回答 2

3

“缓存” .. 好吧,我想你可以这么称呼它。SQLiteOpenHelper通常在内部存储一个(SQLiteDatabase自上次调用创建数据库以来),因此调用#getWritableDatabase()两次将在第二次为您提供相同的对象(除非您关闭第一个实例 - 然后它将再次创建它)。实际上,调用#getReadableDatabase()将尝试以 r/w 方式打开数据库,并且只有在失败时才返回只读实例。

请注意,关闭数据库和调用#getWritableDatabase()不是线程安全的 - 即,SQLiteOpenHelper如果您在许多线程中弄乱它,它可以返回关闭的数据库。

简而言之,您将拥有一个SQLiteDatabase- 但您可以启用锁定 - 使其成为线程安全 - 通过调用SQLiteDatabase#setLockingEnabled(true).

于 2012-05-26T18:24:03.263 回答
2

我有点不清楚正在缓存什么(所以我目前有一个为我做缓存的包装器)。

SQLiteDatabase对象被缓存。

如果我用这个方法创建了两个 SQLiteDatabase 实例,然后关闭一个,另一个仍然是打开的。

假设你只有一个SQLiteOpenHelper,你不能“SQLiteDatabase用这个方法创建两个实例”。第二次getWriteableDatabase()调用返回的结果与SQLiteDatabase第一次调用相同。

如果您仅从单个组件(例如,仅一项活动或仅一项服务)访问数据库,请使用该组件持有的一个SQLiteOpenHelper(并且,通过扩展,仅一项)。SQLiteDatabase如果您从多个组件访问数据库,则需要使用单例SQLiteOpenHelper实例,直接或通过将数据库包装在ContentProvider.

于 2012-05-26T18:22:32.597 回答