一个现在有点想法的IT民工
分类: Android平台
2014-01-06 23:57:43
注意:
(1)这里的异常信息仅仅是android.database.sqlite.SQLiteException: database is locked, 在我研发过程中,还抛出了类似这样的异常信息。该异常是不可以被捕获的。 (2)android.database.sqlite.SQLiteException: database is locked(一些信息)。该异常是可以被捕获的。
这两种异常显然都是数据库被锁异常,但是异常信息不同,说明引起异常的原因也不同。
起初我认为这是由于在我操作数据库的方法前面加了synchronized 的缘故,仔细想想,加这个是避免同时两个线程去写数据库,在逻辑上是完全这确的。去掉之后多线程访问数据库时,会出现数据库关闭的异常,这是由于线程B访问完数据库时,将数据库关闭,线程A再访问数据库引起,它们使用的是同一个数据库对象。
之后,我又查了很多资料,很多人提到了使用继承ContentProvider的方式,来解决该异常。
但是这种方式有2个弊端:
1.使用继承ContentProvider方式,会将项目的数据库暴露给第三方。一般系统级应用,如存储联系人, 存储短信的数据库才有必要暴露给第三方。
2.使用方式不如直接继承SQLiteOpenHelper对象简单。
Android技术文档提到: A content provider is only required if you need to share data between multiple applications. For example, the contacts data is used by multiple applications and must be stored in a content provider. If you don't need to share data amongst multiple applications you can use a database directly via SQLiteDatabase.
如果需要在多个应用之间共享数据的话,ContentProvider方式才应该被使用。例如:联系人数据被多个应用使用,那么它就应该使用在ContentProvider方式存储。如果你不需要共享数据,那么仅仅使用SQLiteDatabase. 数据库就可以了。
现在不使用继承ContentProvider的方式,我们该如何解决以上的异常呢?
The reason a ContentProvider solves the problem is because it usually uses one singleSQLiteOpenHelper which means that there is only one connection to the database and the underlyingSQLiteDatabase takes care of the locking. You don't need a ContentProvider - just make sure you don't write to the DB using 2 different db connections.
A. ContentProvider能解决此问题的原因是它只用一个单一的SQLiteOpenHelper对象,也就是说在app中仅仅有一个“数据库连接” 连接着数据库并且由SQLiteOpenHelper中的SQLiteDatabase负责维护数据库的锁。
B. 你不需要一个ContentProvider - 只要确保不要用2个不同的“数据库连接”去连接数据库就可以了。
以下是我的数据库架构,希望能对大家有所帮助。