Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 房间数据库强制OnCreate回调_Java_Android_Android Room - Fatal编程技术网

Java 房间数据库强制OnCreate回调

Java 房间数据库强制OnCreate回调,java,android,android-room,Java,Android,Android Room,我正在用RoomDatabase开发一个应用程序,它需要预先填充数据;我已经通过添加onCreate()回调实现了这一点,但它只有在第一次访问数据库时才会被调用(比如调用一个Daos函数) 是否有任何方法可以在不执行任何读写操作的情况下强制创建数据库 这是我的代码,MyDatabase.get()在App.onCreate()中调用 是否有任何方法可以在不执行任何读写操作的情况下强制创建数据库 不,对不起 不过,在调用Room之前,没有什么可以阻止您将预填充的数据库复制到适当的位置。您需要确保预

我正在用RoomDatabase开发一个应用程序,它需要预先填充数据;我已经通过添加
onCreate()
回调实现了这一点,但它只有在第一次访问数据库时才会被调用(比如调用一个Daos函数)

是否有任何方法可以在不执行任何读写操作的情况下强制创建数据库

这是我的代码,
MyDatabase.get()
App.onCreate()中调用

是否有任何方法可以在不执行任何读写操作的情况下强制创建数据库

不,对不起


不过,在调用Room之前,没有什么可以阻止您将预填充的数据库复制到适当的位置。您需要确保预填充的数据库中包含文件室的元数据(例如,通过使用文件室本身创建该数据库)。

我花了一段时间才理解为什么在调用数据库生成器上的
.build()
后,文件室数据库没有填充初始数据

对我来说,迁移和回调只在真正的读/写操作中触发,这真的是违反直觉的。实际上,该问题是由Room使用
class RoomOpenHelper
的原因引起的,如文档中所述:

一种打开的帮助程序,在数据库打开之前保存对配置的引用

因此,存储在
RoomOpenHelper
类实例中的配置和所有回调,而Sqlite的
SQLiteOpenHelper
实际上执行数据库迁移,而不是创建(Java中的惰性类加载)

要克服此行为,应执行导致
getWritableDatabase()
的任何操作。我最终采用了以下方法:

RoomDatabase db = Room.databaseBuilder(context,
            ...)
            .build();

  // and then
db.beginTransaction()
db.endTransaction()

  // or query a dummy select statement
db.query("select 1", null)

return db

之后,将创建数据库并填充初始数据。

打开设备文件资源管理器并导航到 /data/data/您的应用程序并删除数据库文件夹

为数据库预填充引入了内置方法:

  • 从应放置在
    assets/
    目录中的预打包数据库文件(*.db)
  • 从预打包的数据库文件(*.db),您应该将其放置在
    assets/
    目录之外的某个位置
  • 有关更多详细信息,请阅读


    获取答案-如何准备您可以阅读的预打包数据库。

    为什么不创建
    应用程序的子类
    ,并在该部分调用您的
    MyDatabase
    singleton?请注意,onCreate只调用一次,除非您删除数据库。因为它位于一个单独的模块中,我不想在其他模块中使用另一个实例,谢谢,正如我猜的那样。我会试试你的suggestion@CommonsWare他的代码是否会使用super.onCreate(db);sInstance.preFillData(上下文);触发onCreate()的递归调用?避免这种情况的唯一方法是:1)从单独的线程调用sInstance.preFillData(上下文),或(2)像在您的书中那样对db对象使用原始SQL查询(但我们失去了房间的类型安全性)。是真的吗?还是你有更好的建议-populating@Ewoks:单独的螺纹在这里会非常危险。相反,您可以在回调外部执行
    preFillData()
    ,但在
    buildDatabase()
    内部执行,其中
    preFillData()
    还检查数据是否以前加载过。如何使用asset force room中已填充的数据库执行此操作删除以前的数据库,然后从资产重新创建它bcz Fallback ToDestructive Migration执行此操作,但使用空数据库,我要重新创建它,然后从资产复制数据库表谢谢!
    RoomDatabase db = Room.databaseBuilder(context,
                ...)
                .build();
    
      // and then
    db.beginTransaction()
    db.endTransaction()
    
      // or query a dummy select statement
    db.query("select 1", null)
    
    return db