39

从 Android 架构组件中使用 Room 时,我在尝试使用 Dagger 组件访问数据库时收到以下错误:

java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: (database path)

我使用的是 Dagger 版本2.11和 Room 版本1.0.0-alpha7。该错误在版本上可重现1.0.0-alpha5

在初始化数据库并将其注入我的类后,任何尝试通过 DAO 访问数据库时都会发生此错误。

4

3 回答 3

87

这是因为您正在尝试修改现有数据库的架构而不提供任何迁移信息。因此,基本上它会尝试将新的数据库模式写入不起作用的现有数据库。

有两种方法可以解决这个问题。如果您在您的开发环境中,您可以做的是回退到破坏性迁移,为此,您的数据库创建代码将如下所示:

MyDatabase myDatabase = Room.databaseBuilder(context, MyDatabase.class, "my-db")
    .fallbackToDestructiveMigration()
    .build();

这意味着当您为数据库提供更新或新实体时,它将按照@huw 的回答执行操作,只需删除应用程序安装中的数据库,从中删除所有数据并重新安装。

另一种方法是使用迁移功能。它们很长,所以除非有人想让我把它写在这里,否则我现在就留下它,但基本上,可以在此处找到文档:

房间数据库迁移文档

这实质上会导致数据库运行一些自己提供的 SQL 来将数据库更新到新版本。这样,您可以确保在进行迁移时不会丢失任何数据;或尽可能少,具体取决于您在做什么。这是生产应用程序的首选方法,因为这意味着用户不会丢失他们预先存在的数据,并且您不会收到很多愤怒的评论/失去的客户。

希望能有所帮助!

于 2017-09-07T15:06:37.363 回答
17

解决此问题的一种方法是删除数据库文件并重新开始。这不是问题,因为我只是在测试并且可以使用在线数据重新填充数据库。

这样做:

  • 应用信息 > 存储 > 清除数据
  • 手动删除文件/data/data/com.app.example/databases/database.db
于 2017-07-28T14:53:14.020 回答
0

在不太成功的迁移之后,我遇到了这种异常。始终仔细检查您用于迁移的 SQL 查询。您可以使用错误类型的数据创建新列,并且异常的描述将无济于事。

于 2018-04-05T20:40:02.953 回答