房间试图重新打开已经关闭的数据库

huw*_*huw 34 android android-room android-architecture-components

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

java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: (database path)
Run Code Online (Sandbox Code Playgroud)

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

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

Jam*_*rem 83

这是因为您尝试修改现有数据库的模式而不向其提供任何迁移信息.所以基本上它会尝试将新的数据库模式写入现有的DB中,但不起作用.

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

MyDatabase myDatabase = Room.databaseBuilder(context, MyDatabase.class, "my-db")
    .fallbackToDestructiveMigration()
    .build();
Run Code Online (Sandbox Code Playgroud)

这意味着当您为数据库提供更新或新实体时,它将执行@huw所说的答案,并删除应用程序安装中的数据库,从中删除所有数据并为您提供全新安装.

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

房间数据库迁移文档

这实际上导致DB运行自己提供的一些SQL来将数据库更新为新版本.这样,您可以确保在执行迁移时不会丢失任何数据; 或尽可能少,取决于你在做什么.这是生产应用程序的首选方法,因为这意味着用户不会丢失预先存在的数据,也不会获得大量愤怒的评论/丢失的客户.

希望有所帮助!

  • 请记住在@Database注释中更改数据库版本.fallbackToDestructiveMigration()不会因为DB结构发生变化而重置DB. (15认同)

huw*_*huw 16

此问题的一个解决方案是删除数据库文件并重新启动.这不是问题,因为我只是测试并且可以使用在线数据重新填充数据库.

要么这样做:

  • 应用信息>存储>清除数据
  • 手动删除文件 /data/data/com.app.example/databases/database.db

  • / data / data / ....的路径不能被android设备直接访问,它应该是root设备才能访问该文件路径。 (2认同)
  • 正确 - 我在一个有根设备上开发,所以这对我有用。(不确定,但您也可以通过 adb 执行此操作?) (2认同)