android - 如何将数据添加到新创建的 Room 数据库?
问题描述
我尝试在 onCreate 方法中导入数据:
db = Room.databaseBuilder(applicationContext,
AppDatabase::class.java,
"my-database")
.allowMainThreadQueries()
//.fallbackToDestructiveMigration()
.addCallback(object: RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
Log.d("RoomDatabase.Callback", "onCreate called")
importData()
}
})
.build()
但这会导致
IllegalStateException:递归调用 getDatabase
在创建数据库后进行导入也不起作用:
var performInitialImport = false
db = Room.databaseBuilder(applicationContext,
AppDatabase::class.java,
"my-database")
.allowMainThreadQueries()
//.fallbackToDestructiveMigration()
.addCallback(object: RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
Log.d("RoomDatabase.Callback", "onCreate called")
performInitialImport = true
}
})
.build()
Log.d("PerformInitialImport", "$performInitialImport")
if (performInitialImport) {
importData()
}
因为在数据库建立后控制流继续之前回调没有被执行。这从以下事实可以看出
D/PerformInitialImport:假
来之前
D/RoomDatabase.Callback: onCreate 调用
在应用程序的运行日志中。
我迷路了。我如何在首次创建时将数据导入数据库?
更新:该importData
方法使用AppDatabase
在第一行创建的实例。db
传递给的参数onCreate
是底层的低级数据库。自然,我想使用 DAO 和我已经拥有的实体来填充数据库......
解决方案
你得到这种行为的原因是构建没有打开数据库,直到你使用数据库才打开它,然后如果数据库不存在,它将被创建并调用 onCreate。
因此performInitialImport将始终为false,除非您访问数据库,强制打开它。
在进行测试之前,您需要打开(访问)数据库。
例子 :-
class MainActivity : AppCompatActivity() {
var firstrun = false
var myTableDao :MyTableDao? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("ROOMBUILD","Building Room Database")
val db = Room.databaseBuilder(this,AppDatabase::class.java,"mydb")
.allowMainThreadQueries()
.addCallback(object: RoomDatabase.Callback()
{
override fun onCreate(db: SupportSQLiteDatabase) {
Log.d("ONCREATE","onCreate called.")
super.onCreate(db)
firstrun = true;
}
}
)
.build()
Log.d("ROOMBUILD","Room database built")
myTableDao = db!!.myTableDao()
//myTableDao!!.getAll() //would also work assuming getAll is defined in the Dao
db.openHelper.writableDatabase //<<<<<<<<<< Force open
if (firstrun) {
importData()
}
for (m in myTableDao!!.getAll()) {
Log.d("MYTABLEINFO","Names is " + m.name + " ID is " + m.id)
}
}
fun importData() {
Log.d("IMPORTING","Data being imported")
var mytable = MyTable()
mytable.name = "MyData"
myTableDao?.insert(mytable)
}
}
结果
安装时:-
2019-11-08 10:36:18.629 D/ROOMBUILD: Building Room Database 2019-11-08 10:36:18.642 D/ROOMBUILD: Room database built 2019-11-08 10:36:18.664 D/ONCREATE: onCreate called. 2019-11-08 10:36:18.669 D/IMPORTING: Data being imported 2019-11-08 10:36:18.675 D/MYTABLEINFO: Names is MyData ID is 1
随后的运行:-
2019-11-08 10:37:07.759 D/ROOMBUILD: Building Room Database 2019-11-08 10:37:07.772 D/ROOMBUILD: Room database built 2019-11-08 10:37:07.789 D/MYTABLEINFO: Names is MyData ID is 1
推荐阅读
- node.js - 如何编译nodejs
- java - 使用自定义请求对象时带有可选参数的 Spring @RequestMapping
- python - 熊猫在日期时间列中给我错误的最大日期?
- reactjs - 在 BrowserRouter 之外使用 Link 测试组件
- spring-boot - Spring Boot响应式WebClient调用遗留端点
- javascript - 访问键值
- c++ - C++ cin.ignore() 跳过循环
- python - 在python中过滤生成的排列
- html - 无法仅使用 CSS 和 HTML 隐藏导航栏
- sql-server - SQL 查找执行所有员工报告到