Android SQLite - 尝试重新打开已经关闭的对象。什么可能关闭我的数据库?

时间:2015-04-20 16:13:52

标签: android sqlite concurrency

我是Android库项目的作者,该项目经常包含在其他应用中。我使用一个小的SQLite数据库进行存储,可以通过android.database.sqlite.SQLiteOpenHelper访问。

当应用程序启动时,数据库助手会创建数据库(如果需要),调用dbHelper.getWritableDatabase(),并使用返回的dbHelper引用进行所有数据库访问。重要提示:

  • 只有帮助者才能访问创建的SQLiteDatabase对象。
  • 我不会随时在数据库上调用SQLiteDatabase.close()。我知道这是这个问题的常见原因,但事实并非如此。
  • 使用我的库的应用程序经常是多线程的。插入是分批完成的,因此同步:

    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()。

这是否可能关闭设备上的所有数据库实例?有没有办法做到这一点?

0 个答案:

没有答案