我是Android库项目的作者,该项目经常包含在其他应用中。我使用一个小的SQLite数据库进行存储,可以通过android.database.sqlite.SQLiteOpenHelper访问。
当应用程序启动时,数据库助手会创建数据库(如果需要),调用dbHelper.getWritableDatabase(),并使用返回的dbHelper引用进行所有数据库访问。重要提示:
使用我的库的应用程序经常是多线程的。插入是分批完成的,因此同步:
public class DatabaseHelper extends SQLiteOpenHelper {
...
...
...
public void insertBatch(LinkedList<DatabaseRecord> writeQueue) {
Iterator<DatabaseRecord> it = writeQueue.iterator();
synchronized (this) {
try {
this.open();
db.beginTransaction();
while (it.hasNext()) {
DatabaseRecord record = it.next();
Long lDate = System.currentTimeMillis() / 1000;
ContentValues initialValues = new ContentValues();
initialValues.put(aa, record.aa);
initialValues.put(bb, record.bb);
initialValues.put(cc, record.cc);
initialValues.put(dd, lDate);
db.insert(DBTBL, null, initialValues);
}
db.setTransactionSuccessful();
} catch (Exception e) {
Utility.logError(logtag, "Error inserting batch record into database.", e);
} finally {
db.endTransaction(); // sometimes throws "already-closed" exception!
this.close();
}
}
}
正如您在评论中看到的那样,问题是endTransaction()调用有时会抛出:
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.xxx.yyy/databases/db near/at android.database.sqlite.SQLiteClosable.acquireReference:55
Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.xxx.yyy/databases/db
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:535)
at com.aaa.bbb.DatabaseHelper.insertBatch(DatabaseHelper.java:273)
at com.aaa.bbb.WriteQueue.flushQueue(WriteQueue.java:88)
at com.aaa.bbb.WriteQueue.run(WriteQueue.java:77)
99.95%的时间有效。但奇怪的是,它在一小部分情况下失败了。在查看失败的位置时,有一个一致性:还有其他SQLite数据库。在这些情况下,还有其他第三方库直接调用SQLiteDatabase.close()。
这是否可能关闭设备上的所有数据库实例?有没有办法做到这一点?