房间持久性错误

时间:2017-09-26 14:13:13

标签: android android-room

我有一个在生产模式下使用Room persistence的应用。它似乎当我尝试更新一个表时,我在某些设备上有以下错误:我与数据库的连接始终打开,只有在销毁时才释放数据库。

这是我的服务,每12小时运行一次

这是服务:https://gist.github.com/anonymous/8fac7650b34aa19229d5f6b91d2454d4 DataRepo: https://gist.github.com/anonymous/70c524c1e8eb5e7ed893131a9c685b5b AppDatabase https://gist.github.com/anonymous/ccb20853054fa5d453592fd2653a4dc4

错误:

java.lang.IllegalStateException: 
     at android.database.sqlite.SQLiteDatabase.throwIfNotOpenLocked 
    (SQLiteDatabase.java:2199)
     at android.database.sqlite.SQLiteDatabase.createSession 
    (SQLiteDatabase.java:379)
    at android.database.sqlite.SQLiteDatabase$1.initialValue 
    (SQLiteDatabase.java:92)
    at android.database.sqlite.SQLiteDatabase$1.initialValue 
    (SQLiteDatabase.java:89)
    at java.lang.ThreadLocal$Values.getAfterMiss (ThreadLocal.java:430)
    at java.lang.ThreadLocal.get (ThreadLocal.java:65)
    at android.database.sqlite.SQLiteDatabase.getThreadSession 
    (SQLiteDatabase.java:373)
    at android.database.sqlite.SQLiteProgram.getSession (SQLiteProgram.java:101)
    at android.database.sqlite.SQLiteStatement.executeUpdateDelete 
    (SQLiteStatement.java:64)
    at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeUpdateDelete (FrameworkSQLiteStatement.java:75)
     at android.arch.persistence.room.EntityDeletionOrUpdateAdapter.handle (EntityDeletionOrUpdateAdapter.java:69)
      at mbc.analytics.sdk.room.dao.TimeDao_Impl.updateTimeModel (TimeDao_Impl.java:122)
      at mbc.analytics.sdk.room.database.DatabaseRepository.createTimeEntity (DatabaseRepository.java:211)
      at mbc.analytics.sdk.room.database.DatabaseRepository.createAppEntity (DatabaseRepository.java:56)
      at mbc.analytics.sdk.services.LollipopService.getStats (LollipopService.java:202)
      at mbc.analytics.sdk.services.LollipopService.access$900 (LollipopService.java:39)
    at mbc.analytics.sdk.services.LollipopService$2.run (LollipopService.java:153)
      at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1112)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587)
      at java.lang.Thread.run (Thread.java:818)

1 个答案:

答案 0 :(得分:2)

DatabaseRepository正在打电话给Room.databaseBuilder()。由于这是使用单例实现的,因此您在调用databaseRepository.databaseClose();时关闭数据库,但不会再次打开。在代码中创建新的DatabaseRepository并不会有帮助,因为AppDatabase.getAppDatabase(ctx);将返回相同的已关闭数据库。

因此,可能的解决方案将是:

  • 删除对databaseRepository.databaseClose();的调用,因为该服务在与其余活动相同的Application内运行,并且数据库已(并且应该)共享。 我认为这是首选解决方案
  • 另一种选择是DatabaseRepository#databaseClose()也会通过调用AppDatabase.destroyInstance();来销毁数据库对象。对我来说,这可能会带来其他问题,例如并发问题,对旧数据库对象的保留引用(例如在活动中)等。

第二个不推荐解决方案的代码:

public void databaseClose() {
    if (db.isOpen()) {
        db.close();
        AppDatabase.destroyInstance();
    }
}